From 23b44ee58fb2846109671f1a3661ec06a5f05fda Mon Sep 17 00:00:00 2001 From: carlos-mejia_nwx Date: Thu, 19 Mar 2026 20:13:29 -0400 Subject: [PATCH 01/62] AA26: Add Access Analyzer v1.0 documentation (266 pages, outline WIP) Co-Authored-By: Claude Opus 4.6 --- .../1.0/activitymonitoring/_category_.json | 10 ++ .../configuration/_category_.json | 10 ++ .../configuration/batchprocessing.md | 8 + .../configuration/connectingnam.md | 8 + .../configuration/enablingsyslog.md | 8 + .../1.0/activitymonitoring/overview.md | 8 + .../viewingdata/_category_.json | 10 ++ .../viewingdata/fileaccessevents.md | 8 + .../viewingdata/useractivitypatterns.md | 8 + docs/accessanalyzer/1.0/admin/_category_.json | 10 ++ .../1.0/admin/auditlogs/_category_.json | 10 ++ .../1.0/admin/auditlogs/export.md | 43 +++++ .../1.0/admin/auditlogs/overview.md | 39 +++++ .../1.0/admin/authentication/_category_.json | 10 ++ .../1.0/admin/authentication/overview.md | 34 ++++ .../admin/authentication/sessionmonitoring.md | 38 +++++ .../1.0/admin/authentication/tokenrefresh.md | 34 ++++ .../1.0/admin/iam/_category_.json | 10 ++ .../1.0/admin/iam/identitiesentitlements.md | 36 +++++ .../1.0/admin/iam/identitysync.md | 43 +++++ docs/accessanalyzer/1.0/admin/iam/overview.md | 32 ++++ .../1.0/admin/iam/permissionpaths.md | 39 +++++ .../1.0/admin/navigate/_category_.json | 10 ++ .../1.0/admin/navigate/datatables.md | 35 ++++ .../1.0/admin/navigate/overview.md | 27 ++++ .../1.0/admin/navigate/sidebar.md | 34 ++++ docs/accessanalyzer/1.0/admin/overview.md | 29 ++++ .../1.0/admin/scans/_category_.json | 10 ++ .../1.0/admin/scans/executionhistory.md | 44 +++++ .../1.0/admin/scans/overview.md | 31 ++++ .../1.0/admin/scans/runningstop.md | 42 +++++ .../1.0/admin/scans/scantypes.md | 64 ++++++++ .../1.0/admin/scans/scheduling.md | 50 ++++++ .../1.0/admin/sensitivedata/_category_.json | 10 ++ .../sensitivedata/customclassification.md | 44 +++++ .../1.0/admin/sensitivedata/overview.md | 34 ++++ .../1.0/admin/sensitivedata/patterngroups.md | 43 +++++ .../1.0/admin/sensitivedata/taxonomygroups.md | 39 +++++ .../1.0/admin/serviceaccounts/_category_.json | 10 ++ .../1.0/admin/serviceaccounts/associating.md | 42 +++++ .../admin/serviceaccounts/credentialtypes.md | 37 +++++ .../1.0/admin/serviceaccounts/overview.md | 33 ++++ .../1.0/admin/settings/_category_.json | 10 ++ .../1.0/admin/settings/featureflags.md | 48 ++++++ .../1.0/admin/settings/overview.md | 33 ++++ .../1.0/admin/settings/scanlimits.md | 37 +++++ .../1.0/admin/settings/sessionttl.md | 41 +++++ .../1.0/admin/sources/_category_.json | 10 ++ .../1.0/admin/sources/editdelete.md | 40 +++++ .../1.0/admin/sources/overview.md | 42 +++++ .../1.0/admin/sources/sourcegroups.md | 51 ++++++ .../1.0/admin/sources/sourcetypes.md | 35 ++++ .../1.0/admin/sources/testconnections.md | 54 +++++++ docs/accessanalyzer/1.0/admin/systemlogs.md | 47 ++++++ .../1.0/admin/users/_category_.json | 10 ++ .../1.0/admin/users/overview.md | 38 +++++ docs/accessanalyzer/1.0/admin/users/roles.md | 36 +++++ .../1.0/admin/users/sessions.md | 35 ++++ .../1.0/connectors/_category_.json | 10 ++ .../1.0/connectors/iam/_category_.json | 10 ++ .../iam/activedirectory/_category_.json | 10 ++ .../iam/activedirectory/connectionsetup.md | 47 ++++++ .../iam/activedirectory/customattributes.md | 12 ++ .../iam/activedirectory/groupmembership.md | 26 +++ .../iam/activedirectory/usergroupsync.md | 30 ++++ .../connectors/iam/entraid/_category_.json | 10 ++ .../connectors/iam/entraid/appregistration.md | 74 +++++++++ .../connectors/iam/entraid/certificateauth.md | 12 ++ .../connectors/iam/entraid/usergroupsync.md | 47 ++++++ .../iam/localgroups/_category_.json | 10 ++ .../iam/localgroups/powershellsetup.md | 52 ++++++ .../iam/localgroups/usergroupcollection.md | 40 +++++ .../1.0/connectors/iam/overview.md | 21 +++ .../accessanalyzer/1.0/connectors/overview.md | 42 +++++ .../1.0/connectors/source/_category_.json | 10 ++ .../connectors/source/cifs/_category_.json | 10 ++ .../source/cifs/connectionconfig.md | 79 +++++++++ .../source/cifs/filevssharelevel.md | 53 +++++++ .../connectors/source/cifs/ntfspermissions.md | 33 ++++ .../source/cifs/scandepthworkers.md | 54 +++++++ .../source/cifs/shareenumeration.md | 53 +++++++ .../1.0/connectors/source/overview.md | 23 +++ .../source/sharepointonline/_category_.json | 10 ++ .../sharepointonline/connectionconfig.md | 44 +++++ .../permissionsharinglinks.md | 35 ++++ .../sharepointonline/scanningspecificsites.md | 30 ++++ .../sharepointonline/sitelibraryenum.md | 29 ++++ .../1.0/dashboards/_category_.json | 10 ++ .../1.0/dashboards/activedirectory.md | 8 + .../1.0/dashboards/copilotreadiness.md | 8 + .../1.0/dashboards/datasecurity.md | 8 + docs/accessanalyzer/1.0/dashboards/entraid.md | 8 + .../1.0/dashboards/metabase/_category_.json | 10 ++ .../dashboards/metabase/accessingreports.md | 36 +++++ .../1.0/dashboards/metabase/exportingdata.md | 41 +++++ .../1.0/dashboards/metabase/savedreports.md | 38 +++++ .../accessanalyzer/1.0/dashboards/overview.md | 33 ++++ .../1.0/gettingstarted/_category_.json | 10 ++ .../gettingstarted/dashboardwalkthrough.md | 44 +++++ .../1.0/gettingstarted/firstlogin.md | 52 ++++++ .../gettingstarted/firstscan/_category_.json | 10 ++ .../gettingstarted/firstscan/addingsource.md | 70 ++++++++ .../firstscan/configuringscan.md | 94 +++++++++++ .../1.0/gettingstarted/firstscan/overview.md | 28 ++++ .../gettingstarted/firstscan/runningscan.md | 56 +++++++ .../firstscan/viewingresults.md | 49 ++++++ .../1.0/gettingstarted/overview.md | 26 +++ docs/accessanalyzer/1.0/index.md | 30 ++++ .../1.0/install/_category_.json | 6 + docs/accessanalyzer/1.0/install/dspmctl.md | 141 ++++++++++++++++ .../1.0/install/environmentvariables.md | 92 +++++++++++ docs/accessanalyzer/1.0/install/network.md | 96 +++++++++++ docs/accessanalyzer/1.0/install/overview.md | 49 ++++++ .../accessanalyzer/1.0/install/postinstall.md | 97 +++++++++++ docs/accessanalyzer/1.0/install/preflight.md | 111 +++++++++++++ .../1.0/install/quickinstall.md | 128 +++++++++++++++ .../1.0/install/requirements.md | 104 ++++++++++++ docs/accessanalyzer/1.0/install/security.md | 65 ++++++++ docs/accessanalyzer/1.0/install/ssl.md | 56 +++++++ docs/accessanalyzer/1.0/install/stepbystep.md | 150 ++++++++++++++++++ docs/accessanalyzer/1.0/install/uninstall.md | 52 ++++++ docs/accessanalyzer/1.0/install/upgrade.md | 77 +++++++++ .../1.0/overview/_category_.json | 10 ++ .../1.0/overview/architecture.md | 69 ++++++++ .../1.0/overview/keyconcepts.md | 87 ++++++++++ docs/accessanalyzer/1.0/overview/overview.md | 36 +++++ .../1.0/requirements/_category_.json | 10 ++ .../requirements/connectors/_category_.json | 10 ++ .../connectors/activedirectory.md | 45 ++++++ .../1.0/requirements/connectors/cifs.md | 52 ++++++ .../1.0/requirements/connectors/entraid.md | 54 +++++++ .../requirements/connectors/localgroups.md | 52 ++++++ .../connectors/sharepointonline.md | 57 +++++++ .../1.0/requirements/database/_category_.json | 10 ++ .../1.0/requirements/database/clickhouse.md | 30 ++++ .../1.0/requirements/database/postgresql.md | 40 +++++ .../1.0/requirements/database/redis.md | 43 +++++ .../1.0/requirements/overview.md | 35 ++++ .../1.0/requirements/system/_category_.json | 10 ++ .../1.0/requirements/system/hardware.md | 84 ++++++++++ .../1.0/requirements/system/kubernetes.md | 53 +++++++ .../1.0/requirements/system/network.md | 64 ++++++++ .../sensitivedatadiscovery/_category_.json | 10 ++ .../1.0/sensitivedatadiscovery/overview.md | 32 ++++ .../patterns/_category_.json | 10 ++ .../patterns/builtinpatterns.md | 34 ++++ .../patterns/custompatterns.md | 47 ++++++ .../patterns/patterngroups.md | 39 +++++ .../reviewingresults/_category_.json | 10 ++ .../classificationbreakdown.md | 43 +++++ .../reviewingresults/matchcounts.md | 46 ++++++ .../1.0/sensitivedatadiscovery/runningscan.md | 43 +++++ .../taxonomy/_category_.json | 10 ++ .../taxonomy/autovscustom.md | 41 +++++ .../taxonomy/classificationrules.md | 40 +++++ .../taxonomy/taxonomygroups.md | 42 +++++ .../1.0/troubleshooting/_category_.json | 10 ++ .../commonissues/_category_.json | 10 ++ .../commonissues/connectionfailures.md | 61 +++++++ .../commonissues/databaseconnectivity.md | 97 +++++++++++ .../commonissues/scanerrors.md | 61 +++++++ .../healthchecks/_category_.json | 10 ++ .../troubleshooting/healthchecks/endpoints.md | 49 ++++++ .../troubleshooting/healthchecks/probes.md | 55 +++++++ .../jobmonitoring/_category_.json | 10 ++ .../jobmonitoring/failedjobs.md | 58 +++++++ .../troubleshooting/jobmonitoring/queues.md | 52 ++++++ .../troubleshooting/jobmonitoring/sidekiq.md | 50 ++++++ .../observability/_category_.json | 10 ++ .../observability/opentelemetry.md | 76 +++++++++ .../observability/prometheus.md | 70 ++++++++ .../1.0/troubleshooting/overview.md | 70 ++++++++ kb_allowlist.json | 1 + sidebars/accessanalyzer/1.0.js | 8 + src/config/products.js | 6 + 175 files changed, 6562 insertions(+) create mode 100644 docs/accessanalyzer/1.0/activitymonitoring/_category_.json create mode 100644 docs/accessanalyzer/1.0/activitymonitoring/configuration/_category_.json create mode 100644 docs/accessanalyzer/1.0/activitymonitoring/configuration/batchprocessing.md create mode 100644 docs/accessanalyzer/1.0/activitymonitoring/configuration/connectingnam.md create mode 100644 docs/accessanalyzer/1.0/activitymonitoring/configuration/enablingsyslog.md create mode 100644 docs/accessanalyzer/1.0/activitymonitoring/overview.md create mode 100644 docs/accessanalyzer/1.0/activitymonitoring/viewingdata/_category_.json create mode 100644 docs/accessanalyzer/1.0/activitymonitoring/viewingdata/fileaccessevents.md create mode 100644 docs/accessanalyzer/1.0/activitymonitoring/viewingdata/useractivitypatterns.md create mode 100644 docs/accessanalyzer/1.0/admin/_category_.json create mode 100644 docs/accessanalyzer/1.0/admin/auditlogs/_category_.json create mode 100644 docs/accessanalyzer/1.0/admin/auditlogs/export.md create mode 100644 docs/accessanalyzer/1.0/admin/auditlogs/overview.md create mode 100644 docs/accessanalyzer/1.0/admin/authentication/_category_.json create mode 100644 docs/accessanalyzer/1.0/admin/authentication/overview.md create mode 100644 docs/accessanalyzer/1.0/admin/authentication/sessionmonitoring.md create mode 100644 docs/accessanalyzer/1.0/admin/authentication/tokenrefresh.md create mode 100644 docs/accessanalyzer/1.0/admin/iam/_category_.json create mode 100644 docs/accessanalyzer/1.0/admin/iam/identitiesentitlements.md create mode 100644 docs/accessanalyzer/1.0/admin/iam/identitysync.md create mode 100644 docs/accessanalyzer/1.0/admin/iam/overview.md create mode 100644 docs/accessanalyzer/1.0/admin/iam/permissionpaths.md create mode 100644 docs/accessanalyzer/1.0/admin/navigate/_category_.json create mode 100644 docs/accessanalyzer/1.0/admin/navigate/datatables.md create mode 100644 docs/accessanalyzer/1.0/admin/navigate/overview.md create mode 100644 docs/accessanalyzer/1.0/admin/navigate/sidebar.md create mode 100644 docs/accessanalyzer/1.0/admin/overview.md create mode 100644 docs/accessanalyzer/1.0/admin/scans/_category_.json create mode 100644 docs/accessanalyzer/1.0/admin/scans/executionhistory.md create mode 100644 docs/accessanalyzer/1.0/admin/scans/overview.md create mode 100644 docs/accessanalyzer/1.0/admin/scans/runningstop.md create mode 100644 docs/accessanalyzer/1.0/admin/scans/scantypes.md create mode 100644 docs/accessanalyzer/1.0/admin/scans/scheduling.md create mode 100644 docs/accessanalyzer/1.0/admin/sensitivedata/_category_.json create mode 100644 docs/accessanalyzer/1.0/admin/sensitivedata/customclassification.md create mode 100644 docs/accessanalyzer/1.0/admin/sensitivedata/overview.md create mode 100644 docs/accessanalyzer/1.0/admin/sensitivedata/patterngroups.md create mode 100644 docs/accessanalyzer/1.0/admin/sensitivedata/taxonomygroups.md create mode 100644 docs/accessanalyzer/1.0/admin/serviceaccounts/_category_.json create mode 100644 docs/accessanalyzer/1.0/admin/serviceaccounts/associating.md create mode 100644 docs/accessanalyzer/1.0/admin/serviceaccounts/credentialtypes.md create mode 100644 docs/accessanalyzer/1.0/admin/serviceaccounts/overview.md create mode 100644 docs/accessanalyzer/1.0/admin/settings/_category_.json create mode 100644 docs/accessanalyzer/1.0/admin/settings/featureflags.md create mode 100644 docs/accessanalyzer/1.0/admin/settings/overview.md create mode 100644 docs/accessanalyzer/1.0/admin/settings/scanlimits.md create mode 100644 docs/accessanalyzer/1.0/admin/settings/sessionttl.md create mode 100644 docs/accessanalyzer/1.0/admin/sources/_category_.json create mode 100644 docs/accessanalyzer/1.0/admin/sources/editdelete.md create mode 100644 docs/accessanalyzer/1.0/admin/sources/overview.md create mode 100644 docs/accessanalyzer/1.0/admin/sources/sourcegroups.md create mode 100644 docs/accessanalyzer/1.0/admin/sources/sourcetypes.md create mode 100644 docs/accessanalyzer/1.0/admin/sources/testconnections.md create mode 100644 docs/accessanalyzer/1.0/admin/systemlogs.md create mode 100644 docs/accessanalyzer/1.0/admin/users/_category_.json create mode 100644 docs/accessanalyzer/1.0/admin/users/overview.md create mode 100644 docs/accessanalyzer/1.0/admin/users/roles.md create mode 100644 docs/accessanalyzer/1.0/admin/users/sessions.md create mode 100644 docs/accessanalyzer/1.0/connectors/_category_.json create mode 100644 docs/accessanalyzer/1.0/connectors/iam/_category_.json create mode 100644 docs/accessanalyzer/1.0/connectors/iam/activedirectory/_category_.json create mode 100644 docs/accessanalyzer/1.0/connectors/iam/activedirectory/connectionsetup.md create mode 100644 docs/accessanalyzer/1.0/connectors/iam/activedirectory/customattributes.md create mode 100644 docs/accessanalyzer/1.0/connectors/iam/activedirectory/groupmembership.md create mode 100644 docs/accessanalyzer/1.0/connectors/iam/activedirectory/usergroupsync.md create mode 100644 docs/accessanalyzer/1.0/connectors/iam/entraid/_category_.json create mode 100644 docs/accessanalyzer/1.0/connectors/iam/entraid/appregistration.md create mode 100644 docs/accessanalyzer/1.0/connectors/iam/entraid/certificateauth.md create mode 100644 docs/accessanalyzer/1.0/connectors/iam/entraid/usergroupsync.md create mode 100644 docs/accessanalyzer/1.0/connectors/iam/localgroups/_category_.json create mode 100644 docs/accessanalyzer/1.0/connectors/iam/localgroups/powershellsetup.md create mode 100644 docs/accessanalyzer/1.0/connectors/iam/localgroups/usergroupcollection.md create mode 100644 docs/accessanalyzer/1.0/connectors/iam/overview.md create mode 100644 docs/accessanalyzer/1.0/connectors/overview.md create mode 100644 docs/accessanalyzer/1.0/connectors/source/_category_.json create mode 100644 docs/accessanalyzer/1.0/connectors/source/cifs/_category_.json create mode 100644 docs/accessanalyzer/1.0/connectors/source/cifs/connectionconfig.md create mode 100644 docs/accessanalyzer/1.0/connectors/source/cifs/filevssharelevel.md create mode 100644 docs/accessanalyzer/1.0/connectors/source/cifs/ntfspermissions.md create mode 100644 docs/accessanalyzer/1.0/connectors/source/cifs/scandepthworkers.md create mode 100644 docs/accessanalyzer/1.0/connectors/source/cifs/shareenumeration.md create mode 100644 docs/accessanalyzer/1.0/connectors/source/overview.md create mode 100644 docs/accessanalyzer/1.0/connectors/source/sharepointonline/_category_.json create mode 100644 docs/accessanalyzer/1.0/connectors/source/sharepointonline/connectionconfig.md create mode 100644 docs/accessanalyzer/1.0/connectors/source/sharepointonline/permissionsharinglinks.md create mode 100644 docs/accessanalyzer/1.0/connectors/source/sharepointonline/scanningspecificsites.md create mode 100644 docs/accessanalyzer/1.0/connectors/source/sharepointonline/sitelibraryenum.md create mode 100644 docs/accessanalyzer/1.0/dashboards/_category_.json create mode 100644 docs/accessanalyzer/1.0/dashboards/activedirectory.md create mode 100644 docs/accessanalyzer/1.0/dashboards/copilotreadiness.md create mode 100644 docs/accessanalyzer/1.0/dashboards/datasecurity.md create mode 100644 docs/accessanalyzer/1.0/dashboards/entraid.md create mode 100644 docs/accessanalyzer/1.0/dashboards/metabase/_category_.json create mode 100644 docs/accessanalyzer/1.0/dashboards/metabase/accessingreports.md create mode 100644 docs/accessanalyzer/1.0/dashboards/metabase/exportingdata.md create mode 100644 docs/accessanalyzer/1.0/dashboards/metabase/savedreports.md create mode 100644 docs/accessanalyzer/1.0/dashboards/overview.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/_category_.json create mode 100644 docs/accessanalyzer/1.0/gettingstarted/dashboardwalkthrough.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/firstlogin.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/firstscan/_category_.json create mode 100644 docs/accessanalyzer/1.0/gettingstarted/firstscan/addingsource.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/firstscan/configuringscan.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/firstscan/overview.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/firstscan/runningscan.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/firstscan/viewingresults.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/overview.md create mode 100644 docs/accessanalyzer/1.0/index.md create mode 100644 docs/accessanalyzer/1.0/install/_category_.json create mode 100644 docs/accessanalyzer/1.0/install/dspmctl.md create mode 100644 docs/accessanalyzer/1.0/install/environmentvariables.md create mode 100644 docs/accessanalyzer/1.0/install/network.md create mode 100644 docs/accessanalyzer/1.0/install/overview.md create mode 100644 docs/accessanalyzer/1.0/install/postinstall.md create mode 100644 docs/accessanalyzer/1.0/install/preflight.md create mode 100644 docs/accessanalyzer/1.0/install/quickinstall.md create mode 100644 docs/accessanalyzer/1.0/install/requirements.md create mode 100644 docs/accessanalyzer/1.0/install/security.md create mode 100644 docs/accessanalyzer/1.0/install/ssl.md create mode 100644 docs/accessanalyzer/1.0/install/stepbystep.md create mode 100644 docs/accessanalyzer/1.0/install/uninstall.md create mode 100644 docs/accessanalyzer/1.0/install/upgrade.md create mode 100644 docs/accessanalyzer/1.0/overview/_category_.json create mode 100644 docs/accessanalyzer/1.0/overview/architecture.md create mode 100644 docs/accessanalyzer/1.0/overview/keyconcepts.md create mode 100644 docs/accessanalyzer/1.0/overview/overview.md create mode 100644 docs/accessanalyzer/1.0/requirements/_category_.json create mode 100644 docs/accessanalyzer/1.0/requirements/connectors/_category_.json create mode 100644 docs/accessanalyzer/1.0/requirements/connectors/activedirectory.md create mode 100644 docs/accessanalyzer/1.0/requirements/connectors/cifs.md create mode 100644 docs/accessanalyzer/1.0/requirements/connectors/entraid.md create mode 100644 docs/accessanalyzer/1.0/requirements/connectors/localgroups.md create mode 100644 docs/accessanalyzer/1.0/requirements/connectors/sharepointonline.md create mode 100644 docs/accessanalyzer/1.0/requirements/database/_category_.json create mode 100644 docs/accessanalyzer/1.0/requirements/database/clickhouse.md create mode 100644 docs/accessanalyzer/1.0/requirements/database/postgresql.md create mode 100644 docs/accessanalyzer/1.0/requirements/database/redis.md create mode 100644 docs/accessanalyzer/1.0/requirements/overview.md create mode 100644 docs/accessanalyzer/1.0/requirements/system/_category_.json create mode 100644 docs/accessanalyzer/1.0/requirements/system/hardware.md create mode 100644 docs/accessanalyzer/1.0/requirements/system/kubernetes.md create mode 100644 docs/accessanalyzer/1.0/requirements/system/network.md create mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/_category_.json create mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/overview.md create mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/_category_.json create mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/builtinpatterns.md create mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/custompatterns.md create mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/patterngroups.md create mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/_category_.json create mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/classificationbreakdown.md create mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/matchcounts.md create mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/runningscan.md create mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/_category_.json create mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/autovscustom.md create mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/classificationrules.md create mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/taxonomygroups.md create mode 100644 docs/accessanalyzer/1.0/troubleshooting/_category_.json create mode 100644 docs/accessanalyzer/1.0/troubleshooting/commonissues/_category_.json create mode 100644 docs/accessanalyzer/1.0/troubleshooting/commonissues/connectionfailures.md create mode 100644 docs/accessanalyzer/1.0/troubleshooting/commonissues/databaseconnectivity.md create mode 100644 docs/accessanalyzer/1.0/troubleshooting/commonissues/scanerrors.md create mode 100644 docs/accessanalyzer/1.0/troubleshooting/healthchecks/_category_.json create mode 100644 docs/accessanalyzer/1.0/troubleshooting/healthchecks/endpoints.md create mode 100644 docs/accessanalyzer/1.0/troubleshooting/healthchecks/probes.md create mode 100644 docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/_category_.json create mode 100644 docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/failedjobs.md create mode 100644 docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/queues.md create mode 100644 docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/sidekiq.md create mode 100644 docs/accessanalyzer/1.0/troubleshooting/observability/_category_.json create mode 100644 docs/accessanalyzer/1.0/troubleshooting/observability/opentelemetry.md create mode 100644 docs/accessanalyzer/1.0/troubleshooting/observability/prometheus.md create mode 100644 docs/accessanalyzer/1.0/troubleshooting/overview.md create mode 100644 sidebars/accessanalyzer/1.0.js diff --git a/docs/accessanalyzer/1.0/activitymonitoring/_category_.json b/docs/accessanalyzer/1.0/activitymonitoring/_category_.json new file mode 100644 index 0000000000..0855f40693 --- /dev/null +++ b/docs/accessanalyzer/1.0/activitymonitoring/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Activity Monitoring", + "position": 90, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/activitymonitoring/configuration/_category_.json b/docs/accessanalyzer/1.0/activitymonitoring/configuration/_category_.json new file mode 100644 index 0000000000..4fda61ea66 --- /dev/null +++ b/docs/accessanalyzer/1.0/activitymonitoring/configuration/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Configuration", + "position": 20, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "enablingsyslog" + } +} diff --git a/docs/accessanalyzer/1.0/activitymonitoring/configuration/batchprocessing.md b/docs/accessanalyzer/1.0/activitymonitoring/configuration/batchprocessing.md new file mode 100644 index 0000000000..807ec75106 --- /dev/null +++ b/docs/accessanalyzer/1.0/activitymonitoring/configuration/batchprocessing.md @@ -0,0 +1,8 @@ +--- +title: "Batch Processing Settings" +description: "Configure batch size and processing intervals" +sidebar_position: 30 +draft: true +--- + +# Batch Processing Settings diff --git a/docs/accessanalyzer/1.0/activitymonitoring/configuration/connectingnam.md b/docs/accessanalyzer/1.0/activitymonitoring/configuration/connectingnam.md new file mode 100644 index 0000000000..3f9bdba5f0 --- /dev/null +++ b/docs/accessanalyzer/1.0/activitymonitoring/configuration/connectingnam.md @@ -0,0 +1,8 @@ +--- +title: "Connecting Netwrix Activity Monitor" +description: "Configure NAM to send events to Access Analyzer" +sidebar_position: 20 +draft: true +--- + +# Connecting Netwrix Activity Monitor diff --git a/docs/accessanalyzer/1.0/activitymonitoring/configuration/enablingsyslog.md b/docs/accessanalyzer/1.0/activitymonitoring/configuration/enablingsyslog.md new file mode 100644 index 0000000000..ed154c8585 --- /dev/null +++ b/docs/accessanalyzer/1.0/activitymonitoring/configuration/enablingsyslog.md @@ -0,0 +1,8 @@ +--- +title: "Enabling Syslog Ingestion" +description: "Enable the syslog listener for activity data" +sidebar_position: 10 +draft: true +--- + +# Enabling Syslog Ingestion diff --git a/docs/accessanalyzer/1.0/activitymonitoring/overview.md b/docs/accessanalyzer/1.0/activitymonitoring/overview.md new file mode 100644 index 0000000000..1db4669826 --- /dev/null +++ b/docs/accessanalyzer/1.0/activitymonitoring/overview.md @@ -0,0 +1,8 @@ +--- +title: "Activity Monitoring" +description: "Monitor file access and user activity via Netwrix Activity Monitor" +sidebar_position: 1 +draft: true +--- + +# Activity Monitoring diff --git a/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/_category_.json b/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/_category_.json new file mode 100644 index 0000000000..0f66039da8 --- /dev/null +++ b/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Viewing Activity Data", + "position": 30, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "fileaccessevents" + } +} diff --git a/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/fileaccessevents.md b/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/fileaccessevents.md new file mode 100644 index 0000000000..e914857e32 --- /dev/null +++ b/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/fileaccessevents.md @@ -0,0 +1,8 @@ +--- +title: "File Access Events" +description: "Viewing file access event data" +sidebar_position: 10 +draft: true +--- + +# File Access Events diff --git a/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/useractivitypatterns.md b/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/useractivitypatterns.md new file mode 100644 index 0000000000..b22d570ef1 --- /dev/null +++ b/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/useractivitypatterns.md @@ -0,0 +1,8 @@ +--- +title: "User Activity Patterns" +description: "Analyzing user activity trends and patterns" +sidebar_position: 20 +draft: true +--- + +# User Activity Patterns diff --git a/docs/accessanalyzer/1.0/admin/_category_.json b/docs/accessanalyzer/1.0/admin/_category_.json new file mode 100644 index 0000000000..8ba9f88730 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Administration", + "position": 50, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/admin/auditlogs/_category_.json b/docs/accessanalyzer/1.0/admin/auditlogs/_category_.json new file mode 100644 index 0000000000..08737ee73a --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/auditlogs/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Audit Logs", + "position": 100, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/admin/auditlogs/export.md b/docs/accessanalyzer/1.0/admin/auditlogs/export.md new file mode 100644 index 0000000000..5f46de33f4 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/auditlogs/export.md @@ -0,0 +1,43 @@ +--- +title: "Log Export" +description: "Exporting audit log data" +sidebar_position: 20 +--- + +# Log Export + +Administrators can export audit log data for external analysis, compliance reporting, or long-term archival. The export feature generates a downloadable file containing the filtered audit log entries. + +## Exporting Logs + +To export audit logs: + +1. Navigate to **Audit Logs** in the sidebar. +2. Apply any desired filters (date range, user, action type, resource type) to narrow the export scope. +3. Click **Export**. +4. Select the export format: + +| Format | Description | +|---|---| +| **CSV** | Comma-separated values, compatible with spreadsheet applications and data analysis tools | +| **JSON** | Structured JSON format, suitable for programmatic processing and SIEM ingestion | + +5. Click **Download** to save the file. + +## Export Scope + +The export includes all audit log entries matching the current filter criteria. If no filters are applied, the export contains all available audit log records. + +:::note +Large exports may take several minutes to generate. The download begins automatically when the file is ready. +::: + +## Use Cases + +- **Compliance Audits** -- Provide auditors with a complete trail of administrative actions over a specified period. +- **SIEM Integration** -- Export logs in JSON format for ingestion into security information and event management platforms. +- **Archival** -- Periodically export and archive audit logs to external storage for long-term retention. + +:::warning +Exported audit log files may contain sensitive information about users and system configuration. Handle exported files in accordance with your organization's data handling policies. +::: diff --git a/docs/accessanalyzer/1.0/admin/auditlogs/overview.md b/docs/accessanalyzer/1.0/admin/auditlogs/overview.md new file mode 100644 index 0000000000..fa30bc76ae --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/auditlogs/overview.md @@ -0,0 +1,39 @@ +--- +title: "Audit Logs" +description: "Viewing system activity and audit trail" +sidebar_position: 10 +--- + +# Audit Logs + +Access Analyzer maintains a comprehensive audit trail of all user actions. Audit logs capture who performed an action, what was changed, and when the event occurred. This data supports security reviews, compliance audits, and incident investigations. + +## Viewing Audit Logs + +Navigate to **Audit Logs** in the sidebar to access the log viewer. The audit log table displays: + +| Column | Description | +|---|---| +| **Timestamp** | Date and time of the action | +| **User** | The user who performed the action | +| **Action** | The type of operation (e.g., Create, Update, Delete, Login, Logout) | +| **Resource** | The affected resource type and identifier | +| **Details** | Additional context about the change, including before and after values where applicable | +| **IP Address** | The client IP from which the action was performed | + +## Filtering and Searching + +Use the table controls to filter audit logs by: + +- **Date range** -- Specify start and end dates. +- **User** -- Filter by a specific user. +- **Action type** -- Show only specific action types. +- **Resource type** -- Filter by resource category (e.g., Source, Scan, User). + +## Log Retention + +Audit logs are retained for the duration configured in application settings. By default, logs are retained indefinitely. + +## Related Topics + +- [Log Export](/docs/accessanalyzer/1_0/admin/auditlogs/export) diff --git a/docs/accessanalyzer/1.0/admin/authentication/_category_.json b/docs/accessanalyzer/1.0/admin/authentication/_category_.json new file mode 100644 index 0000000000..b4206ec509 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/authentication/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Authentication", + "position": 30, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/admin/authentication/overview.md b/docs/accessanalyzer/1.0/admin/authentication/overview.md new file mode 100644 index 0000000000..cea13a2a43 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/authentication/overview.md @@ -0,0 +1,34 @@ +--- +title: "Authentication" +description: "Login workflow and session lifecycle" +sidebar_position: 10 +--- + +# Authentication + +Access Analyzer uses session-based authentication backed by Redis for secure, server-side session storage. All API endpoints under `/api/v1/` require a valid session, except for the login endpoint. + +## Login Workflow + +1. The user submits their **username** and **password** via the login form. +2. The server validates the credentials against the stored Argon2id password hash. +3. On success, a new session is created in Redis and a session cookie is returned to the client. +4. The client includes the session cookie with all subsequent API requests. + +## Session Lifecycle + +Each session progresses through the following states: + +- **Active** -- The session is valid and the user is authenticated. +- **Refreshed** -- The session token has been refreshed before expiration. See [Token Refresh and Expiration](/docs/accessanalyzer/1_0/admin/authentication/tokenrefresh). +- **Expired** -- The session TTL has elapsed and the user must re-authenticate. +- **Revoked** -- An administrator has manually terminated the session. + +## IP Validation + +Access Analyzer validates the client IP address on each request. If a request originates from an IP that does not match the session's originating IP, the session is invalidated and the user must log in again. + +## Related Topics + +- [Token Refresh and Expiration](/docs/accessanalyzer/1_0/admin/authentication/tokenrefresh) +- [Session Monitoring and Revocation](/docs/accessanalyzer/1_0/admin/authentication/sessionmonitoring) diff --git a/docs/accessanalyzer/1.0/admin/authentication/sessionmonitoring.md b/docs/accessanalyzer/1.0/admin/authentication/sessionmonitoring.md new file mode 100644 index 0000000000..15ad434a40 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/authentication/sessionmonitoring.md @@ -0,0 +1,38 @@ +--- +title: "Session Monitoring and Revocation" +description: "Monitoring active sessions and revoking access" +sidebar_position: 30 +--- + +# Session Monitoring and Revocation + +Administrators can monitor all active sessions across the application and revoke access when needed. This is useful for responding to security incidents or enforcing access policies. + +## Monitoring Active Sessions + +The session monitoring view is accessible from **Users** > **Sessions**. It provides a real-time view of all authenticated sessions, including: + +- **Username** and assigned role +- **Client IP address** and geographic context +- **Session start time** and **last activity** timestamp +- **Remaining TTL** before automatic expiration + +Use the table's filter and sort controls to locate specific sessions by user, IP address, or activity time. + +## Revoking Sessions + +To revoke one or more sessions: + +1. Select the target sessions using the row checkboxes. +2. Click **Revoke Selected**. +3. Confirm the action in the dialog. + +Revocation is immediate. The affected sessions are removed from Redis and all subsequent requests using those session tokens return `401 Unauthorized`. + +## Bulk Revocation + +To revoke all sessions for a specific user, navigate to the user's detail page and click **Revoke All Sessions**. This is recommended when a user account may be compromised. + +:::warning +Session revocation cannot be undone. Affected users must log in again to regain access. +::: diff --git a/docs/accessanalyzer/1.0/admin/authentication/tokenrefresh.md b/docs/accessanalyzer/1.0/admin/authentication/tokenrefresh.md new file mode 100644 index 0000000000..ee1dbd8250 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/authentication/tokenrefresh.md @@ -0,0 +1,34 @@ +--- +title: "Token Refresh and Expiration" +description: "How access tokens are refreshed and session expiration" +sidebar_position: 20 +--- + +# Token Refresh and Expiration + +Access Analyzer sessions have a configurable time-to-live (TTL). To prevent unnecessary re-authentication, sessions are automatically refreshed during active use. + +## How Token Refresh Works + +When a user makes an API request and the session is past the halfway point of its TTL, the server automatically issues a new session token. This process is transparent to the user: + +1. The client sends a request with the current session cookie. +2. The server detects that the session has passed 50% of its TTL. +3. A new session token is generated and the old token is invalidated. +4. The response includes the updated session cookie. + +## Session Expiration + +Sessions expire when the full TTL elapses without any qualifying refresh. When a session expires: + +- All subsequent API requests return a `401 Unauthorized` response. +- The user is redirected to the login page. +- The expired session record is automatically purged from Redis. + +## Configuration + +Session TTL and refresh behavior are configured in the application settings. See [Session and Token TTL](/docs/accessanalyzer/1_0/admin/settings/sessionttl) for configuration details. + +:::note +Token refresh only occurs during active requests. Background tabs or idle browser windows do not trigger a refresh. +::: diff --git a/docs/accessanalyzer/1.0/admin/iam/_category_.json b/docs/accessanalyzer/1.0/admin/iam/_category_.json new file mode 100644 index 0000000000..762c39d494 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/iam/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "IAM Services", + "position": 80, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/admin/iam/identitiesentitlements.md b/docs/accessanalyzer/1.0/admin/iam/identitiesentitlements.md new file mode 100644 index 0000000000..d0fedf9ee1 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/iam/identitiesentitlements.md @@ -0,0 +1,36 @@ +--- +title: "Viewing Identities and Entitlements" +description: "Browsing synced users and their permissions" +sidebar_position: 30 +--- + +# Viewing Identities and Entitlements + +After identity synchronization completes, administrators and viewers can browse the unified identity directory and review entitlements across all scanned sources. + +## Identity List + +Navigate to **IAM** > **Identities** to view all synced identities. The table displays: + +| Column | Description | +|---|---| +| **Display Name** | The user or group name | +| **Type** | User or Group | +| **Provider** | Source directory (Active Directory, Entra ID, Local Groups) | +| **Email** | Associated email address, if available | +| **Group Count** | Number of groups the identity belongs to | +| **Last Synced** | Timestamp of the most recent sync | + +Use the filter controls to narrow results by provider, type, or keyword search. + +## Entitlement Details + +Click an identity to open the detail view, which includes: + +- **Group Memberships** -- All groups the identity belongs to, including nested group membership. +- **Resource Access** -- A list of sources and resources the identity can access, with the effective permission level. +- **Permission Paths** -- Links to the [Permission Path Analysis](/docs/accessanalyzer/1_0/admin/iam/permissionpaths) for each access entry, showing how the permission was granted. + +## Cross-Provider Correlation + +When the same user exists in multiple directories, Access Analyzer correlates these identities and displays a unified view. Correlated accounts are indicated with a badge showing the linked providers. diff --git a/docs/accessanalyzer/1.0/admin/iam/identitysync.md b/docs/accessanalyzer/1.0/admin/iam/identitysync.md new file mode 100644 index 0000000000..784bd209da --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/iam/identitysync.md @@ -0,0 +1,43 @@ +--- +title: "Identity Sync Process" +description: "How identities are synchronized from IAM providers" +sidebar_position: 20 +--- + +# Identity Sync Process + +Identity synchronization imports user and group data from configured IAM providers into Access Analyzer. This data forms the foundation for entitlement analysis and permission path reporting. + +## How Sync Works + +The identity sync process performs the following steps: + +1. Connects to each configured IAM source (Active Directory, Entra ID, or Local Groups) using the associated service account credentials. +2. Retrieves user accounts, groups, and membership relationships. +3. Normalizes identity data into a unified format across providers. +4. Stores the synchronized identities in the Access Analyzer database. +5. Correlates identities across multiple providers when the same user appears in more than one directory. + +## Triggering a Sync + +Identity sync occurs automatically during access scan execution. It can also be triggered manually: + +1. Navigate to **IAM** in the sidebar. +2. Click **Sync Now**. +3. Monitor the sync progress in the status indicator. + +## Sync Frequency + +Each access scan triggers a fresh identity sync for its target sources. For environments that change frequently, schedule access scans at regular intervals to keep identity data current. + +## Sync Status + +| Status | Description | +|---|---| +| **In Progress** | Sync is actively importing identity data | +| **Completed** | Sync finished successfully with a timestamp | +| **Failed** | Sync encountered an error; check system logs for details | + +:::note +Identity sync only imports identity metadata (usernames, group names, memberships). It does not import passwords or other credential data. +::: diff --git a/docs/accessanalyzer/1.0/admin/iam/overview.md b/docs/accessanalyzer/1.0/admin/iam/overview.md new file mode 100644 index 0000000000..60b42bffc2 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/iam/overview.md @@ -0,0 +1,32 @@ +--- +title: "IAM Services" +description: "Configuring identity and access management integrations" +sidebar_position: 10 +--- + +# IAM Services + +The IAM section provides tools for synchronizing identities from external directories and analyzing access entitlements across your environment. This enables centralized visibility into who has access to what resources and how that access was granted. + +## Supported IAM Providers + +Access Analyzer synchronizes identity data from the following sources: + +| Provider | Identity Data | +|---|---| +| **Active Directory** | Users, groups, group memberships, organizational units | +| **Entra ID** | Users, groups, application role assignments | +| **Local Groups** | Local users and group memberships on Windows servers | + +## Key Capabilities + +- **Identity Synchronization** -- Import users and groups from configured IAM providers. See [Identity Sync Process](/docs/accessanalyzer/1_0/admin/iam/identitysync). +- **Identities and Entitlements** -- Browse synced identities and view their effective permissions across sources. See [Viewing Identities and Entitlements](/docs/accessanalyzer/1_0/admin/iam/identitiesentitlements). +- **Permission Path Analysis** -- Trace the path from a user to a resource to understand how access was granted. See [Permission Path Analysis](/docs/accessanalyzer/1_0/admin/iam/permissionpaths). + +## Prerequisites + +Before using IAM features, ensure that: + +- At least one Active Directory, Entra ID, or Local Groups source is configured with valid credentials. +- An access scan has been completed for the target sources. diff --git a/docs/accessanalyzer/1.0/admin/iam/permissionpaths.md b/docs/accessanalyzer/1.0/admin/iam/permissionpaths.md new file mode 100644 index 0000000000..c119a02184 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/iam/permissionpaths.md @@ -0,0 +1,39 @@ +--- +title: "Permission Path Analysis" +description: "Analyzing permission paths and access relationships" +sidebar_position: 40 +--- + +# Permission Path Analysis + +Permission path analysis traces the chain of access from an identity to a resource, showing every group membership, permission assignment, and inheritance step that grants access. This is essential for understanding why a user has access to a particular resource. + +## Viewing Permission Paths + +To view permission paths for a specific identity: + +1. Navigate to **IAM** > **Identities** and select the target identity. +2. In the **Resource Access** section, click the **View Path** link next to any resource entry. + +The permission path visualization displays the chain as a directional graph: + +**User** > **Group** > **Nested Group** > **Permission Assignment** > **Resource** + +## Path Components + +| Component | Description | +|---|---| +| **Identity** | The starting user or group | +| **Group Membership** | Direct or nested group that the identity belongs to | +| **Permission Entry** | The specific ACL or role assignment that grants access | +| **Resource** | The target file share, site, directory object, or folder | + +## Use Cases + +- **Access Reviews** -- Determine whether a user's access is appropriate and through which path it was granted. +- **Least Privilege Analysis** -- Identify overly broad group memberships that grant unintended access. +- **Incident Response** -- Trace access paths for a compromised account to assess the scope of exposure. + +:::note +Permission paths are computed from the most recent access scan results. Run a new scan to capture changes in group memberships or permission assignments. +::: diff --git a/docs/accessanalyzer/1.0/admin/navigate/_category_.json b/docs/accessanalyzer/1.0/admin/navigate/_category_.json new file mode 100644 index 0000000000..b9960d7f84 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/navigate/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Navigating the Web Interface", + "position": 10, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/admin/navigate/datatables.md b/docs/accessanalyzer/1.0/admin/navigate/datatables.md new file mode 100644 index 0000000000..4c976fa57d --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/navigate/datatables.md @@ -0,0 +1,35 @@ +--- +title: "Data Tables" +description: "Sorting, filtering, and pagination in data tables" +sidebar_position: 30 +--- + +# Data Tables + +Data tables are used throughout the Access Analyzer interface to display collections of records such as sources, scans, users, and audit log entries. Each table supports sorting, filtering, and pagination. + +## Sorting + +Click a column header to sort the table by that column. Click the same header again to toggle between ascending and descending order. A directional arrow icon indicates the current sort direction. + +## Filtering + +Use the filter controls above the table to narrow results: + +- **Text search** -- Enter a keyword to filter rows that match across visible columns. +- **Column filters** -- Some tables provide dropdown filters for specific columns such as status, type, or date range. + +## Pagination + +Tables with large datasets are paginated. Use the controls at the bottom of the table to: + +- Navigate between pages using **Previous** and **Next** buttons. +- Select the number of rows displayed per page (e.g., 10, 25, 50, 100). + +## Bulk Actions + +On supported tables, select one or more rows using the checkbox column to enable bulk actions. Available bulk actions vary by context and may include **Delete**, **Run Scan**, or **Export**. + +:::note +Table state (sort order, active filters, current page) resets when you navigate away from the page. +::: diff --git a/docs/accessanalyzer/1.0/admin/navigate/overview.md b/docs/accessanalyzer/1.0/admin/navigate/overview.md new file mode 100644 index 0000000000..9662e7ffe0 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/navigate/overview.md @@ -0,0 +1,27 @@ +--- +title: "Navigating the Web Interface" +description: "Overview of the Access Analyzer web interface" +sidebar_position: 10 +--- + +# Navigating the Web Interface + +Netwrix Access Analyzer provides a web-based interface for managing all configuration and reporting tasks. The interface is organized into a persistent sidebar for primary navigation and a main content area that displays contextual data tables, forms, and dashboards. + +## Interface Layout + +The web interface consists of the following regions: + +- **Sidebar** -- The left-hand navigation panel provides access to all major sections including Sources, Scans, IAM, Sensitive Data, Settings, and Audit Logs. See [Sidebar Navigation](/docs/accessanalyzer/1_0/admin/navigate/sidebar) for details. +- **Header bar** -- Displays the current user, session status, and a logout control. +- **Main content area** -- Renders the active page content including data tables, detail views, and configuration forms. + +## Key Concepts + +- Most list views use paginated [Data Tables](/docs/accessanalyzer/1_0/admin/navigate/datatables) with sorting, filtering, and search capabilities. +- Breadcrumbs at the top of the content area indicate your current location in the navigation hierarchy. +- Action buttons such as **Create**, **Edit**, and **Delete** appear contextually based on the active page and your user role. + +:::note +The interface requires a modern web browser with JavaScript enabled. Supported browsers include the latest versions of Chrome, Edge, and Firefox. +::: diff --git a/docs/accessanalyzer/1.0/admin/navigate/sidebar.md b/docs/accessanalyzer/1.0/admin/navigate/sidebar.md new file mode 100644 index 0000000000..db30881ccf --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/navigate/sidebar.md @@ -0,0 +1,34 @@ +--- +title: "Sidebar Navigation" +description: "Using the sidebar to navigate between sections" +sidebar_position: 20 +--- + +# Sidebar Navigation + +The sidebar is the primary navigation element in the Access Analyzer web interface. It remains visible on every page and provides direct access to all major administration sections. + +## Sidebar Sections + +The sidebar contains the following top-level entries: + +| Section | Purpose | +|---|---| +| **Dashboard** | Application overview and summary metrics | +| **Sources** | Manage data sources and source groups | +| **Scans** | Create, schedule, and monitor scans | +| **IAM** | View synced identities, entitlements, and permission paths | +| **Sensitive Data** | Configure classification patterns and taxonomy rules | +| **Service Accounts** | Manage credentials for source connections | +| **Settings** | Application-wide configuration | +| **Audit Logs** | Review user action history | +| **System Logs** | View application and job processing logs | +| **Users** | Manage user accounts and sessions | + +## Collapsible Groups + +Some sidebar entries expand to reveal sub-items. Click a section label to toggle its children. The currently active page is highlighted with a visual indicator. + +## Role-Based Visibility + +Users with the **Viewer** role see a reduced sidebar. Administrative sections such as **Settings** and **Users** are hidden for non-administrator accounts. diff --git a/docs/accessanalyzer/1.0/admin/overview.md b/docs/accessanalyzer/1.0/admin/overview.md new file mode 100644 index 0000000000..0b759ccd84 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/overview.md @@ -0,0 +1,29 @@ +--- +title: "Administration" +description: "Manage users, sources, scans, and system settings" +sidebar_position: 1 +--- + +# Administration + +The Administration section provides tools for configuring and managing all aspects of Netwrix Access Analyzer. From here, administrators can control user access, define data sources, configure scans, and maintain system settings. + +## Admin Sections + +| Section | Description | +|---|---| +| [Navigation](/docs/accessanalyzer/1_0/admin/navigate/overview) | Learn how to navigate the web interface, use the sidebar, and interact with data tables | +| [Users](/docs/accessanalyzer/1_0/admin/users/overview) | Create and manage user accounts, assign roles, and monitor sessions | +| [Authentication](/docs/accessanalyzer/1_0/admin/authentication/overview) | Configure login workflows, session lifecycle, and token management | +| [Sources](/docs/accessanalyzer/1_0/admin/sources/overview) | Add and manage data sources for scanning | +| [Service Accounts](/docs/accessanalyzer/1_0/admin/serviceaccounts/overview) | Manage credentials used to connect to data sources | +| [Scans](/docs/accessanalyzer/1_0/admin/scans/overview) | Create, schedule, and monitor access and sensitive data scans | +| [Sensitive Data](/docs/accessanalyzer/1_0/admin/sensitivedata/overview) | Configure classification patterns, taxonomy groups, and compliance mappings | +| [IAM](/docs/accessanalyzer/1_0/admin/iam/overview) | Synchronize identities and analyze entitlements and permission paths | +| [Settings](/docs/accessanalyzer/1_0/admin/settings/overview) | Configure application-wide settings, scan limits, and feature flags | +| [Audit Logs](/docs/accessanalyzer/1_0/admin/auditlogs/overview) | Review and export the full user action audit trail | +| [System Logs](/docs/accessanalyzer/1_0/admin/systemlogs) | View application-level system logs and Sidekiq job monitoring | + +:::note +Only users with the **Administrator** role have full access to all administration functions. Users with the **Viewer** role have read-only access. +::: diff --git a/docs/accessanalyzer/1.0/admin/scans/_category_.json b/docs/accessanalyzer/1.0/admin/scans/_category_.json new file mode 100644 index 0000000000..27b262b756 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/scans/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Scan Management", + "position": 60, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/admin/scans/executionhistory.md b/docs/accessanalyzer/1.0/admin/scans/executionhistory.md new file mode 100644 index 0000000000..4afaf84df1 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/scans/executionhistory.md @@ -0,0 +1,44 @@ +--- +title: "Scan Execution History" +description: "Viewing scan status and execution history" +sidebar_position: 50 +--- + +# Scan Execution History + +Every scan execution is recorded with detailed status information, timing, and result summaries. The execution history provides a complete audit trail of all scan activity. + +## Viewing Execution History + +To view a scan's history: + +1. Navigate to **Scans** and click the target scan. +2. Select the **History** tab in the detail view. + +The history table displays each execution with the following columns: + +| Column | Description | +|---|---| +| **Run ID** | Unique identifier for the execution | +| **Status** | Final status (Completed, Failed, Stopped) | +| **Started At** | Timestamp when the execution began | +| **Completed At** | Timestamp when the execution ended | +| **Duration** | Total elapsed time | +| **Items Processed** | Number of resources scanned | +| **Findings** | Count of access entries or sensitive data matches found | + +## Execution Details + +Click a specific execution row to view detailed results including: + +- Per-source breakdown of items scanned and findings +- Error messages for failed executions +- Resource utilization metrics + +## Retention + +Execution history records are retained indefinitely. To manage storage, administrators can export and archive older records through the [Audit Logs](/docs/accessanalyzer/1_0/admin/auditlogs/overview) export feature. + +:::note +Execution history for deleted scans is also removed. Export any needed data before deleting a scan. +::: diff --git a/docs/accessanalyzer/1.0/admin/scans/overview.md b/docs/accessanalyzer/1.0/admin/scans/overview.md new file mode 100644 index 0000000000..fb917e14a4 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/scans/overview.md @@ -0,0 +1,31 @@ +--- +title: "Scan Management" +description: "Creating and managing scans" +sidebar_position: 10 +--- + +# Scan Management + +Scans are the core operational unit in Access Analyzer. A scan defines what sources to analyze, what type of analysis to perform, and when to execute. Administrators create and manage scans from the **Scans** section. + +## Creating Scans + +Scans are typically created as part of the **Connect Source** wizard (Step 3), where you configure scan types, options, and scheduling alongside the source group. The wizard creates all scans atomically with the source group and sources. + +Scans can also be managed independently after creation: + +1. Navigate to **Scans** in the sidebar. +2. Select a scan to view or edit its configuration. +3. Modify the schedule, scan options, or other settings. +4. Click **Save**. + +## Scan List + +The scan list displays all configured scans with their name, type, target sources, schedule, last execution status, and next scheduled run time. Use the data table controls to filter and sort. + +## Related Topics + +- [Scan Types](/docs/accessanalyzer/1_0/admin/scans/scantypes) +- [Scheduling Scans](/docs/accessanalyzer/1_0/admin/scans/scheduling) +- [Running and Stopping Scans](/docs/accessanalyzer/1_0/admin/scans/runningstop) +- [Scan Execution History](/docs/accessanalyzer/1_0/admin/scans/executionhistory) diff --git a/docs/accessanalyzer/1.0/admin/scans/runningstop.md b/docs/accessanalyzer/1.0/admin/scans/runningstop.md new file mode 100644 index 0000000000..3df1773d7f --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/scans/runningstop.md @@ -0,0 +1,42 @@ +--- +title: "Running and Stopping Scans" +description: "Executing scans and graceful stop" +sidebar_position: 40 +--- + +# Running and Stopping Scans + +Administrators can manually trigger scan execution and control running scans through the web interface. These controls are available from the scan detail view and the scan list. + +## Running a Scan Manually + +To start a scan immediately: + +1. Navigate to **Scans** in the sidebar. +2. Locate the scan and click **Run** (or open the detail view and click **Run Now**). +3. The scan status changes to **Running** and progress is displayed in real time. + +## Scan Controls + +While a scan is running, the following controls are available: + +| Action | Description | +|---|---| +| **Pause** | Temporarily suspends scan execution. The scan can be resumed from where it stopped. | +| **Resume** | Continues a paused scan from its last checkpoint. | +| **Stop** | Initiates a graceful stop. The scan finishes processing the current item and then terminates. | + +## Scan Status Values + +| Status | Meaning | +|---|---| +| **Pending** | The scan is queued and waiting to start | +| **Running** | The scan is actively processing | +| **Paused** | The scan is suspended and can be resumed | +| **Completing** | The scan is finishing its current work unit after a stop request | +| **Completed** | The scan finished successfully | +| **Failed** | The scan terminated due to an error | + +:::warning +Stopping a scan does not roll back any data already collected. Partial results are retained and visible in the scan history. +::: diff --git a/docs/accessanalyzer/1.0/admin/scans/scantypes.md b/docs/accessanalyzer/1.0/admin/scans/scantypes.md new file mode 100644 index 0000000000..39ba1911a2 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/scans/scantypes.md @@ -0,0 +1,64 @@ +--- +title: "Scan Types" +description: "Access, sensitive data, identity sync, and local users scan types" +sidebar_position: 20 +--- + +# Scan Types + +Access Analyzer supports several scan types, each designed to analyze different aspects of your data environment. Scan types are selected during the Connect Source wizard (Step 3) and determine what data is collected and reported. + +## Access Scans + +Access scans analyze permissions and access controls on the target sources. They collect: + +- User and group permission assignments +- Effective access rights +- Permission inheritance paths +- Share and folder-level access control lists + +Access scans are available for **CIFS** (File Server), **SharePoint**, **Active Directory**, and **Local Groups** source types. + +For File Server sources, access scans support additional configuration options including share filtering, scan depth, file-level permissions, hidden share enumeration, and worker threads. See [CIFS Connector](/docs/accessanalyzer/1_0/connectors/source/cifs/connectionconfig) for details. + +## Sensitive Data Scans + +Sensitive data scans inspect file content to identify data matching configured classification patterns. They detect: + +- Personally identifiable information (PII) +- Financial data (credit card numbers, bank account numbers) +- Protected health information (PHI) +- Credentials and secrets +- Custom patterns defined in [Sensitive Data Configuration](/docs/accessanalyzer/1_0/admin/sensitivedata/overview) + +Sensitive data scans are available for **CIFS** and **SharePoint** source types only. + +## Identity Sync Scans + +Identity sync scans retrieve users, groups, and permissions from identity providers: + +| Scan | Source Type | Description | +| --- | --- | --- | +| **Active Directory Inventory** | Active Directory | Synchronizes users, groups, OUs, and domain permissions | +| **Users, Groups and Roles** | Entra ID | Synchronizes Azure AD users, groups, directory roles, and optionally sensitivity labels | + +For Entra ID, the identity sync scan is always enabled and cannot be disabled. + +## Local Users and Groups Scans + +When an **Access** scan is enabled for a File Server source, a **Local Users and Groups** scan is automatically created alongside it. This scan collects local user and group account data from each file server, which is used to resolve local account references found in NTFS ACLs. + +This scan type does not require separate configuration — it inherits the same schedule as the access scan. + +## Comparison + +| Feature | Access Scan | Sensitive Data Scan | Identity Sync | Local Users and Groups | +|---|---|---|---|---| +| Analyzes permissions | Yes | No | No | No | +| Inspects file content | No | Yes | No | No | +| Syncs identities | No | No | Yes | Yes | +| Supported sources | CIFS, SharePoint, AD, Local Groups | CIFS, SharePoint | AD, Entra ID | CIFS (auto-created) | + +:::note +A single source can have multiple scan types configured independently, each with its own schedule. +::: diff --git a/docs/accessanalyzer/1.0/admin/scans/scheduling.md b/docs/accessanalyzer/1.0/admin/scans/scheduling.md new file mode 100644 index 0000000000..f1088e482d --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/scans/scheduling.md @@ -0,0 +1,50 @@ +--- +title: "Scheduling Scans" +description: "Configuring cron-based scan schedules" +sidebar_position: 30 +--- + +# Scheduling Scans + +Scans can be configured to run automatically on a recurring schedule using cron expressions. Scheduled scans are processed by the Sidekiq background job system. + +## Setting a Schedule + +To schedule a scan: + +1. Navigate to **Scans** and open the scan detail view. +2. Click **Edit**. +3. In the **Schedule** section, enable **Scheduled Execution**. +4. Enter a cron expression or use the visual schedule builder to define the frequency. +5. Click **Save**. + +## Cron Expression Format + +Schedules use standard five-field cron syntax: + +``` +* * * * * +| | | | | +| | | | +-- Day of week (0-6, Sunday=0) +| | | +---- Month (1-12) +| | +------ Day of month (1-31) +| +-------- Hour (0-23) ++---------- Minute (0-59) +``` + +**Examples:** + +| Expression | Description | +|---|---| +| `0 2 * * *` | Daily at 2:00 AM | +| `0 0 * * 0` | Weekly on Sunday at midnight | +| `0 6 1 * *` | Monthly on the 1st at 6:00 AM | +| `0 */4 * * *` | Every 4 hours | + +## Disabling a Schedule + +To stop a scan from running automatically, edit the scan and disable **Scheduled Execution**. The scan configuration is preserved and can be re-enabled later or run manually. + +:::note +All schedule times are interpreted in the server's configured timezone. +::: diff --git a/docs/accessanalyzer/1.0/admin/sensitivedata/_category_.json b/docs/accessanalyzer/1.0/admin/sensitivedata/_category_.json new file mode 100644 index 0000000000..6b56ea467a --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/sensitivedata/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Sensitive Data Configuration", + "position": 70, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/admin/sensitivedata/customclassification.md b/docs/accessanalyzer/1.0/admin/sensitivedata/customclassification.md new file mode 100644 index 0000000000..732fcd762f --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/sensitivedata/customclassification.md @@ -0,0 +1,44 @@ +--- +title: "Custom Classification" +description: "Creating custom classification rules" +sidebar_position: 40 +--- + +# Custom Classification + +In addition to built-in patterns, administrators can create custom classification rules to detect organization-specific sensitive data types. Custom rules use regular expressions and integrate with the existing pattern and taxonomy group framework. + +## Creating a Custom Pattern + +To create a custom pattern: + +1. Navigate to **Sensitive Data** > **Pattern Groups**. +2. Select an existing group or click **Create Group** to define a new pattern group. +3. Click **Add Pattern**. +4. Complete the following fields: + +| Field | Description | +|---|---| +| **Name** | A descriptive label (e.g., "Internal Employee ID") | +| **Regex** | The regular expression to match against file content | +| **Confidence** | Expected accuracy level: **High**, **Medium**, or **Low** | +| **Description** | Optional notes about what the pattern detects | + +5. Click **Save**. + +## Creating a Custom Pattern Group + +Custom pattern groups organize related custom patterns under a shared label. To create a group: + +1. Click **Create Group** from the Pattern Groups page. +2. Enter a **Name** and optional **Description**. +3. Add one or more patterns to the group. +4. Click **Save**. + +## Mapping Custom Patterns to Taxonomy Groups + +To include custom patterns in compliance reporting, associate the custom pattern group with one or more taxonomy groups. Edit the taxonomy group and add the custom pattern group to its list of associated patterns. + +:::warning +Test custom regex patterns thoroughly before enabling them in production scans. Overly broad patterns can generate excessive false positives and impact scan performance. +::: diff --git a/docs/accessanalyzer/1.0/admin/sensitivedata/overview.md b/docs/accessanalyzer/1.0/admin/sensitivedata/overview.md new file mode 100644 index 0000000000..ba8d0bb074 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/sensitivedata/overview.md @@ -0,0 +1,34 @@ +--- +title: "Sensitive Data Configuration" +description: "Configuring patterns and classification rules" +sidebar_position: 10 +--- + +# Sensitive Data Configuration + +The Sensitive Data section allows administrators to configure how Access Analyzer identifies and classifies sensitive information during scans. Classification is driven by regex-based patterns organized into pattern groups and taxonomy groups. + +## How Classification Works + +During a sensitive data scan, Access Analyzer inspects file content against all enabled patterns. When a match is found, the file is tagged with the corresponding classification labels and compliance framework mappings. + +## Configuration Components + +| Component | Description | +|---|---| +| [Pattern Groups](/docs/accessanalyzer/1_0/admin/sensitivedata/patterngroups) | Collections of regex patterns that define what constitutes sensitive data (e.g., PII, Credentials) | +| [Taxonomy Groups](/docs/accessanalyzer/1_0/admin/sensitivedata/taxonomygroups) | Compliance-oriented groupings that map patterns to regulatory frameworks (e.g., GDPR, HIPAA) | +| [Custom Classification](/docs/accessanalyzer/1_0/admin/sensitivedata/customclassification) | User-defined patterns and rules for organization-specific data types | + +## Built-in Categories + +Access Analyzer ships with built-in patterns for common sensitive data categories: + +- **PII** -- Social Security numbers, email addresses, phone numbers, names +- **Credentials** -- API keys, passwords, connection strings, tokens +- **PHI** -- Medical record numbers, diagnosis codes, patient identifiers +- **Financial** -- Credit card numbers, bank account numbers, routing numbers + +:::note +Built-in patterns cannot be deleted but can be disabled if they are not relevant to your environment. +::: diff --git a/docs/accessanalyzer/1.0/admin/sensitivedata/patterngroups.md b/docs/accessanalyzer/1.0/admin/sensitivedata/patterngroups.md new file mode 100644 index 0000000000..2179380a16 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/sensitivedata/patterngroups.md @@ -0,0 +1,43 @@ +--- +title: "Patterns and Pattern Groups" +description: "Managing regex patterns and pattern groups" +sidebar_position: 20 +--- + +# Patterns and Pattern Groups + +Patterns are regular expressions that Access Analyzer uses to identify sensitive data within file content. Patterns are organized into groups for easier management and selective enablement. + +## Pattern Groups + +A pattern group is a named collection of related patterns. Built-in groups include: + +| Group | Examples | +|---|---| +| **PII** | Social Security numbers, driver's license numbers, passport numbers | +| **Credentials** | API keys, passwords in config files, SSH private keys | +| **PHI** | Medical record numbers, health plan IDs, diagnosis codes | +| **Financial** | Credit card numbers (Visa, MasterCard, Amex), IBAN, routing numbers | + +## Managing Patterns + +To view and manage patterns within a group: + +1. Navigate to **Sensitive Data** > **Pattern Groups**. +2. Select a group to view its patterns. +3. Each pattern displays its name, regex expression, and enabled/disabled status. + +Administrators can enable or disable individual patterns within a group. Disabled patterns are excluded from scan matching. + +## Pattern Fields + +| Field | Description | +|---|---| +| **Name** | Descriptive label for the pattern | +| **Regex** | The regular expression used for matching | +| **Confidence** | Expected match accuracy (High, Medium, Low) | +| **Enabled** | Whether the pattern is active during scans | + +:::note +Changes to pattern enablement take effect on the next scan execution. Running scans use the configuration that was active at scan start time. +::: diff --git a/docs/accessanalyzer/1.0/admin/sensitivedata/taxonomygroups.md b/docs/accessanalyzer/1.0/admin/sensitivedata/taxonomygroups.md new file mode 100644 index 0000000000..ff36f4f0b9 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/sensitivedata/taxonomygroups.md @@ -0,0 +1,39 @@ +--- +title: "Taxonomy Groups and Rules" +description: "Configuring taxonomy-based data classification" +sidebar_position: 30 +--- + +# Taxonomy Groups and Rules + +Taxonomy groups map pattern detections to compliance frameworks and regulatory standards. They provide a compliance-oriented view of sensitive data findings. + +## Built-in Compliance Mappings + +Access Analyzer includes pre-configured taxonomy groups aligned to major regulatory frameworks: + +| Taxonomy Group | Framework | Relevant Data Types | +|---|---|---| +| **GDPR** | General Data Protection Regulation | PII, personal data, EU resident identifiers | +| **CCPA** | California Consumer Privacy Act | PII, consumer records, financial identifiers | +| **HIPAA** | Health Insurance Portability and Accountability Act | PHI, medical records, health plan data | +| **PCI DSS** | Payment Card Industry Data Security Standard | Credit card numbers, cardholder data | +| **GLBA** | Gramm-Leach-Bliley Act | Financial records, account numbers | +| **CMMC** | Cybersecurity Maturity Model Certification | Controlled unclassified information, credentials | + +## How Taxonomy Mapping Works + +Each taxonomy group references one or more pattern groups. When a sensitive data scan produces a match against a pattern, the finding is automatically tagged with all associated taxonomy labels. This enables compliance-focused reporting without additional configuration. + +## Managing Taxonomy Groups + +To view taxonomy group configuration: + +1. Navigate to **Sensitive Data** > **Taxonomy Groups**. +2. Select a group to view its associated patterns and compliance mappings. + +Administrators can enable or disable taxonomy groups to control which compliance labels appear in scan results. + +:::note +Built-in taxonomy groups are updated with product releases to reflect changes in regulatory standards. +::: diff --git a/docs/accessanalyzer/1.0/admin/serviceaccounts/_category_.json b/docs/accessanalyzer/1.0/admin/serviceaccounts/_category_.json new file mode 100644 index 0000000000..85d0158bb9 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/serviceaccounts/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Service Accounts", + "position": 50, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/admin/serviceaccounts/associating.md b/docs/accessanalyzer/1.0/admin/serviceaccounts/associating.md new file mode 100644 index 0000000000..cd3479356a --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/serviceaccounts/associating.md @@ -0,0 +1,42 @@ +--- +title: "Associating with Sources" +description: "Linking service accounts to data sources" +sidebar_position: 30 +--- + +# Associating with Sources + +Each data source requires an associated service account to authenticate when connecting to the target environment. A single service account can be shared across multiple sources of compatible types. + +## Assigning a Service Account to a Source + +Service accounts are assigned during source creation or by editing an existing source: + +1. Navigate to **Sources** and open the source detail view. +2. Click **Edit**. +3. In the **Service Account** field, select the desired account from the dropdown. +4. Click **Save**. + +The dropdown only shows service accounts with a credential type compatible with the selected source type. + +## Changing the Associated Account + +To switch a source to a different service account, edit the source and select a new account. The change takes effect on the next scan execution. Running scans continue to use the previously assigned account until completion. + +## Disassociating a Service Account + +To remove a service account association, edit the source and clear the **Service Account** field, then assign a replacement. Sources cannot be saved without a service account. + +:::note +Verify connectivity after changing service account associations by running a [Test Connection](/docs/accessanalyzer/1_0/admin/sources/testconnections). +::: + +## Compatibility Matrix + +| Source Type | Username/Password | OAuth2 Client Credentials | Certificate | +|---|---|---|---| +| CIFS | Yes | No | No | +| SharePoint | No | Yes | Yes | +| Active Directory | Yes | No | No | +| Entra ID | No | Yes | Yes | +| Local Groups | Yes | No | No | diff --git a/docs/accessanalyzer/1.0/admin/serviceaccounts/credentialtypes.md b/docs/accessanalyzer/1.0/admin/serviceaccounts/credentialtypes.md new file mode 100644 index 0000000000..7dc69e4b2f --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/serviceaccounts/credentialtypes.md @@ -0,0 +1,37 @@ +--- +title: "Credential Types" +description: "Supported credential types and configurations" +sidebar_position: 20 +--- + +# Credential Types + +Access Analyzer supports three credential types for service accounts. The appropriate type depends on the target source and its authentication requirements. Service accounts can be created ahead of time from the **Service Accounts** page, or inline during the Connect Source wizard. + +## Supported Types + +| Credential Type | Description | Typical Use | +|---|---|---| +| **Username/Password** | Standard username and password pair | CIFS file shares, Active Directory, Local Groups | +| **OAuth2 Client Credentials** | Client ID and client secret for OAuth2 flows | Entra ID | +| **Certificate** | X.509 certificate with private key | SharePoint Online | + +## Username/Password + +Provide a **Username** and **Password**. The password is encrypted at rest. For Active Directory and file server sources, use the `DOMAIN\username` or `username@domain.com` format. + +Used by the **File Server** and **Active Directory** wizards. During the wizard, click **+ Create New Account** to create a username/password service account inline. + +## OAuth2 Client Credentials + +Provide a **Client ID** and **Client Secret**. These credentials are used in the OAuth2 client credentials grant flow to obtain an access token from the identity provider. + +Used by the **Entra ID** wizard. The Client ID and Client Secret come from an Azure AD app registration — see [App Registration and Permissions](/docs/accessanalyzer/1_0/connectors/iam/entraid/appregistration) for setup instructions. + +## Certificate + +Upload a **Certificate** file (PEM or PFX format) and provide the **Private Key** or PFX password. Certificate-based authentication is used for SharePoint Online connections. + +:::note +Credential values are stored encrypted and cannot be viewed after creation. To update credentials, edit the service account and provide new values. +::: diff --git a/docs/accessanalyzer/1.0/admin/serviceaccounts/overview.md b/docs/accessanalyzer/1.0/admin/serviceaccounts/overview.md new file mode 100644 index 0000000000..aed048051c --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/serviceaccounts/overview.md @@ -0,0 +1,33 @@ +--- +title: "Service Accounts" +description: "Managing credentials for data source connections" +sidebar_position: 10 +--- + +# Service Accounts + +Service accounts store the credentials that Access Analyzer uses to connect to and authenticate against data sources. Each service account is configured with a specific credential type and can be associated with one or more sources. + +## Creating a Service Account + +To create a service account: + +1. Navigate to **Service Accounts** in the sidebar. +2. Click **Create Service Account**. +3. Enter a **Name** and optional **Description**. +4. Select the [credential type](/docs/accessanalyzer/1_0/admin/serviceaccounts/credentialtypes) (Username/Password, OAuth2 Client Credentials, or Certificate). +5. Provide the required credential fields. +6. Click **Save**. + +## Service Account List + +The service account list displays all configured accounts with their name, credential type, number of associated sources, and creation date. Credentials are never displayed in plaintext after initial creation. + +## Editing and Deleting + +- **Edit** -- Update the name, description, or credential values. Changing credentials takes effect on the next scan execution. +- **Delete** -- Remove a service account. This operation fails if the account is currently associated with any sources. + +:::warning +Before deleting a service account, disassociate it from all sources. See [Associating with Sources](/docs/accessanalyzer/1_0/admin/serviceaccounts/associating). +::: diff --git a/docs/accessanalyzer/1.0/admin/settings/_category_.json b/docs/accessanalyzer/1.0/admin/settings/_category_.json new file mode 100644 index 0000000000..2e922ee742 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/settings/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Application Settings", + "position": 90, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/admin/settings/featureflags.md b/docs/accessanalyzer/1.0/admin/settings/featureflags.md new file mode 100644 index 0000000000..e40dbea10d --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/settings/featureflags.md @@ -0,0 +1,48 @@ +--- +title: "Feature Flags" +description: "Runtime feature toggles and configuration" +sidebar_position: 40 +--- + +# Feature Flags + +Feature flags allow administrators to enable or disable specific application capabilities at runtime without restarting the service. Flags are defined in the `app_settings.yml` configuration file and can be overridden through the web interface. + +## Viewing Feature Flags + +Navigate to **Settings** > **Feature Flags** to see all available flags, their current state, and descriptions. + +## Configuration File + +Feature flags are declared in `app_settings.yml` on the application server: + +```yaml +feature_flags: + sensitive_data_scanning: true + identity_correlation: true + audit_log_export: true + advanced_permission_paths: false +``` + +## Overriding via the Web Interface + +To toggle a feature flag: + +1. Navigate to **Settings** > **Feature Flags**. +2. Locate the flag and toggle its state. +3. Click **Save**. + +Web interface overrides take precedence over values in `app_settings.yml`. To revert to the file-based value, click **Reset to Default** next to the flag. + +## Common Feature Flags + +| Flag | Description | +|---|---| +| `sensitive_data_scanning` | Enables or disables the sensitive data scan type | +| `identity_correlation` | Enables cross-provider identity matching in IAM | +| `audit_log_export` | Enables the audit log export functionality | +| `advanced_permission_paths` | Enables detailed permission path visualization | + +:::warning +Disabling a feature flag immediately removes the associated functionality from the web interface for all users. Running operations that depend on a disabled flag may fail. +::: diff --git a/docs/accessanalyzer/1.0/admin/settings/overview.md b/docs/accessanalyzer/1.0/admin/settings/overview.md new file mode 100644 index 0000000000..f7268f3fb5 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/settings/overview.md @@ -0,0 +1,33 @@ +--- +title: "Application Settings" +description: "Global application configuration options" +sidebar_position: 10 +--- + +# Application Settings + +The Settings section provides administrators with controls over global application behavior. Configuration changes made here affect all users and system operations. + +## Settings Categories + +| Category | Description | +|---|---| +| [Concurrent Scan Limits](/docs/accessanalyzer/1_0/admin/settings/scanlimits) | Control the maximum number of scans that can execute simultaneously | +| [Session and Token TTL](/docs/accessanalyzer/1_0/admin/settings/sessionttl) | Configure session duration and token refresh intervals | +| [Feature Flags](/docs/accessanalyzer/1_0/admin/settings/featureflags) | Enable or disable application features at runtime | + +## Accessing Settings + +Navigate to **Settings** in the sidebar. Only users with the **Administrator** role can view and modify settings. + +## Saving Changes + +After modifying a setting, click **Save** to apply the change. Most settings take effect immediately. Settings that require a service restart display a notification indicating when the change will be applied. + +:::warning +Changing application settings can affect system behavior for all users. Review changes carefully before saving, and coordinate with other administrators when modifying production configurations. +::: + +## Configuration File + +Some advanced settings are managed through the `app_settings.yml` configuration file on the server. Settings modified through the web interface override values in the configuration file. See [Feature Flags](/docs/accessanalyzer/1_0/admin/settings/featureflags) for details on file-based configuration. diff --git a/docs/accessanalyzer/1.0/admin/settings/scanlimits.md b/docs/accessanalyzer/1.0/admin/settings/scanlimits.md new file mode 100644 index 0000000000..8711666a0c --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/settings/scanlimits.md @@ -0,0 +1,37 @@ +--- +title: "Concurrent Scan Limits" +description: "Configuring maximum concurrent scan execution" +sidebar_position: 20 +--- + +# Concurrent Scan Limits + +Access Analyzer limits the number of scans that can run simultaneously to manage system resource consumption. Administrators configure these limits based on available server capacity. + +## Configuration + +To configure scan limits: + +1. Navigate to **Settings** in the sidebar. +2. Locate the **Concurrent Scan Limits** section. +3. Set the desired values and click **Save**. + +## Available Settings + +| Setting | Description | Default | +|---|---|---| +| **Max Concurrent Access Scans** | Maximum number of access scans running at the same time | 5 | +| **Max Concurrent Sensitive Data Scans** | Maximum number of sensitive data scans running at the same time | 3 | +| **Max Total Concurrent Scans** | Combined limit across all scan types | 8 | + +## Behavior When Limits Are Reached + +When a scan is triggered (manually or by schedule) and the concurrent limit has been reached, the scan enters a **Pending** state and is queued. Queued scans start automatically as running scans complete, in first-in-first-out order. + +:::note +Sensitive data scans are typically more resource-intensive than access scans. Consider setting a lower concurrent limit for sensitive data scans to avoid impacting system performance. +::: + +## Monitoring + +View the current number of running and queued scans from the **Scans** list page. The status column indicates whether each scan is **Running**, **Pending**, or **Queued**. diff --git a/docs/accessanalyzer/1.0/admin/settings/sessionttl.md b/docs/accessanalyzer/1.0/admin/settings/sessionttl.md new file mode 100644 index 0000000000..00d6f81382 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/settings/sessionttl.md @@ -0,0 +1,41 @@ +--- +title: "Session and Token TTL" +description: "Configuring session duration and token refresh intervals" +sidebar_position: 30 +--- + +# Session and Token TTL + +Session and token TTL (time-to-live) settings control how long user sessions remain valid and when tokens are refreshed. These settings balance security requirements with user convenience. + +## Configuration + +To configure session TTL: + +1. Navigate to **Settings** in the sidebar. +2. Locate the **Session Configuration** section. +3. Adjust the values and click **Save**. + +## Available Settings + +| Setting | Description | Default | +|---|---|---| +| **Session TTL** | Maximum lifetime of a session, in minutes | 480 (8 hours) | +| **Idle Timeout** | Time of inactivity before a session expires, in minutes | 60 | +| **Token Refresh Threshold** | Percentage of TTL elapsed before automatic token refresh occurs | 50% | + +## How TTL Affects Users + +- When the **Session TTL** expires, the user is logged out regardless of activity. +- When the **Idle Timeout** elapses without any API requests, the session expires. +- Active sessions are automatically refreshed when the elapsed time exceeds the **Token Refresh Threshold**, extending the session without user intervention. + +See [Token Refresh and Expiration](/docs/accessanalyzer/1_0/admin/authentication/tokenrefresh) for details on the refresh mechanism. + +:::warning +Setting very long session TTLs increases the window of exposure if a session token is compromised. Follow your organization's security policies when configuring these values. +::: + +## Session Storage + +Sessions are stored in Redis. Ensure the Redis instance has sufficient memory to accommodate all active sessions, especially in environments with many concurrent users. diff --git a/docs/accessanalyzer/1.0/admin/sources/_category_.json b/docs/accessanalyzer/1.0/admin/sources/_category_.json new file mode 100644 index 0000000000..ac24200ff0 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/sources/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Data Source Management", + "position": 40, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/admin/sources/editdelete.md b/docs/accessanalyzer/1.0/admin/sources/editdelete.md new file mode 100644 index 0000000000..41b634770e --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/sources/editdelete.md @@ -0,0 +1,40 @@ +--- +title: "Editing and Deleting Sources" +description: "Modifying and removing data sources" +sidebar_position: 40 +--- + +# Editing and Deleting Sources + +Administrators can modify source configuration or remove sources that are no longer needed. Both operations are available from the source detail view. + +## Editing a Source + +To edit a source: + +1. Navigate to **Sources** and click the target source to open its detail view. +2. Click **Edit**. +3. Update the desired fields such as connection parameters, display name, or associated service account. +4. Click **Save**. + +:::note +The source type cannot be changed after creation. To use a different type, create a new source and delete the old one. +::: + +## Deleting a Source + +To delete a source: + +1. Open the source detail view. +2. Click **Delete**. +3. Confirm the deletion in the dialog. + +:::warning +Deleting a source removes all associated scan configurations and execution history. This action cannot be undone. Export any required scan results before deleting. +::: + +## Impact on Related Resources + +- **Scans** -- Any scans targeting the deleted source are also removed. +- **Source Groups** -- The source is automatically removed from any groups it belonged to. +- **Scan Results** -- Historical scan result data associated with the source is permanently deleted. diff --git a/docs/accessanalyzer/1.0/admin/sources/overview.md b/docs/accessanalyzer/1.0/admin/sources/overview.md new file mode 100644 index 0000000000..f23e5217a5 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/sources/overview.md @@ -0,0 +1,42 @@ +--- +title: "Data Source Management" +description: "Adding and managing data sources" +sidebar_position: 10 +--- + +# Data Source Management + +Sources represent the target environments that Access Analyzer connects to for scanning. Sources are organized into **source groups** — named collections that share a service account and configuration. Administrators create, edit, test, and delete sources from the **Sources** section. + +## Adding Sources + +Sources are created through the **Connect Source** wizard, a 3-step guided workflow: + +1. Navigate to **Sources** in the sidebar. +2. Click **Connect Source** to open the wizard drawer. +3. **Step 1** — Select the [source type](/docs/accessanalyzer/1_0/admin/sources/sourcetypes) (File Server, Active Directory, Entra ID, or SharePoint). +4. **Step 2** — Name the source group, assign a [service account](/docs/accessanalyzer/1_0/admin/serviceaccounts/overview), and add one or more sources. +5. **Step 3** — Configure scan types, scan options, and scheduling. +6. Click **Complete Setup** to create the source group, sources, and scans in one operation. + +The wizard uses the `POST /v1/source-groups/setup` endpoint to create all resources atomically. + +### Source Group Behavior by Type + +| Source Type | Sources per Group | Notes | +| --- | --- | --- | +| **File Server** | Multiple | Add many servers with shared service account and domain | +| **Active Directory** | Multiple | Add multiple domain controllers | +| **Entra ID** | Single | One Azure AD tenant per group | +| **SharePoint Online** | Multiple | Add multiple site collections | + +## Source List + +The sources list displays all configured sources with their name, type, connection status, and associated service account. Use the data table controls to filter by type or search by name. + +## Related Topics + +- [Source Types and Configuration](/docs/accessanalyzer/1_0/admin/sources/sourcetypes) +- [Testing Connections](/docs/accessanalyzer/1_0/admin/sources/testconnections) +- [Editing and Deleting Sources](/docs/accessanalyzer/1_0/admin/sources/editdelete) +- [Source Groups](/docs/accessanalyzer/1_0/admin/sources/sourcegroups) diff --git a/docs/accessanalyzer/1.0/admin/sources/sourcegroups.md b/docs/accessanalyzer/1.0/admin/sources/sourcegroups.md new file mode 100644 index 0000000000..13bce1ba62 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/sources/sourcegroups.md @@ -0,0 +1,51 @@ +--- +title: "Source Groups" +description: "Organizing sources into groups with shared configuration" +sidebar_position: 50 +--- + +# Source Groups + +A source group is a named collection of related sources that share a common service account, configuration, and scan settings. Source groups are the primary organizational unit for sources in Access Analyzer. + +## How Source Groups Work + +Source groups are created through the **Connect Source** wizard, which creates the group, all its sources, and associated scans in a single atomic operation. Each source group has: + +- A **name** to identify the group +- A **source type** (all sources in the group are the same type) +- A **service account** shared by all sources in the group +- One or more **sources** (the actual connection targets) +- One or more **scans** with a shared schedule + +## Source Groups by Type + +| Source Type | Sources per Group | Example | +| --- | --- | --- | +| **File Server** | Multiple servers | `Finance File Servers` with `fs01`, `fs02`, `fs03` — all sharing one service account and domain | +| **Active Directory** | Multiple domain controllers | `Corp AD` with `dc01`, `dc02` | +| **Entra ID** | Single tenant | `Corporate Entra ID` with one Azure AD tenant | +| **SharePoint Online** | Multiple site collections | `Marketing SharePoint` with several sites | + +## Creating a Source Group + +Source groups are created exclusively through the Connect Source wizard: + +1. Navigate to **Sources** in the sidebar +2. Click **Connect Source** +3. Follow the 3-step wizard: select source type, configure sources, set up scans +4. Click **Complete Setup** + +For detailed instructions, see [Adding a Data Source](/docs/accessanalyzer/1_0/gettingstarted/firstscan/addingsource). + +## Viewing Source Groups + +The sources list displays individual sources, each showing its parent source group. You can filter by source group to see all sources within a group. + +## Deleting a Source Group + +Deleting a source group removes the group, all its sources, and all associated scans. + +:::warning +Deleting a source group is permanent and removes all sources and scan configurations within it. Scan execution history is preserved for audit purposes. +::: diff --git a/docs/accessanalyzer/1.0/admin/sources/sourcetypes.md b/docs/accessanalyzer/1.0/admin/sources/sourcetypes.md new file mode 100644 index 0000000000..55f2f7cc4d --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/sources/sourcetypes.md @@ -0,0 +1,35 @@ +--- +title: "Source Types and Configuration" +description: "Available source types and their configuration parameters" +sidebar_position: 20 +--- + +# Source Types and Configuration + +Access Analyzer supports multiple source types, each targeting a different data environment. The source type determines the required connection parameters and the kinds of scans available. + +## Available Source Types + +| Source Type | Description | Supported Scans | +|---|---|---| +| **CIFS** | Windows file shares accessed via SMB/CIFS protocol | Access, Sensitive Data | +| **SharePoint** | Microsoft SharePoint Online or on-premises sites | Access, Sensitive Data | +| **Active Directory** | On-premises Active Directory domains | Access | +| **Entra ID** | Microsoft Entra ID (formerly Azure AD) tenants | Access | +| **Local Groups** | Local user and group membership on Windows servers | Access | + +## Configuration Parameters + +Each source type requires specific connection details: + +- **CIFS** -- Server hostname or IP, share path, and port number. +- **SharePoint** -- Site URL, authentication method, and tenant ID. +- **Active Directory** -- Domain controller hostname, base DN, and LDAP port. +- **Entra ID** -- Tenant ID, client ID, and authentication secret or certificate. +- **Local Groups** -- Target server hostname or IP address. + +All source types require an associated [service account](/docs/accessanalyzer/1_0/admin/serviceaccounts/overview) with appropriate credentials for the target environment. + +:::note +Source type cannot be changed after creation. To switch types, delete the existing source and create a new one. +::: diff --git a/docs/accessanalyzer/1.0/admin/sources/testconnections.md b/docs/accessanalyzer/1.0/admin/sources/testconnections.md new file mode 100644 index 0000000000..ff5de9a3c1 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/sources/testconnections.md @@ -0,0 +1,54 @@ +--- +title: "Testing Connections" +description: "Validating source connectivity before scanning" +sidebar_position: 30 +--- + +# Testing Connections + +Before running scans, verify that Access Analyzer can reach and authenticate to each configured source using the test connection feature. Connection testing is available both during source creation (in the wizard) and on existing sources. + +## Testing During Source Creation + +The Connect Source wizard includes a **Test Connection** button in Step 2: + +- **File Server** — Tests all servers in parallel. Each server shows its own status: **Connected** (green), **Failed** (red), or **Testing** (spinner). A summary toast shows the overall result (for example, "All 3 connections successful" or "1 of 3 failed"). +- **Entra ID** — Tests the OAuth2 connection to the specified Azure AD tenant. Status appears inline: "Successfully connected to Entra ID" or "Connection failed" with an error message. +- **Active Directory** — Tests connectivity to each domain controller. + +:::note +Connection testing in the wizard is non-blocking. You can proceed to the next step regardless of test results. +::: + +## Testing Existing Sources + +To test an existing source connection: + +1. Navigate to **Sources** in the sidebar. +2. Locate the source in the list and click its row to open the detail view. +3. Click **Test Connection**. +4. Wait for the test to complete. Results appear inline. + +## What Gets Tested + +The test connection operation sends a request to `POST /v1/sources/test-connection` with the source's connection parameters. It validates: + +| Check | Description | +|---|---| +| **Network Reachability** | Confirms the target host and port are accessible from the application server | +| **Authentication** | Verifies the associated service account credentials are accepted | +| **Authorization** | Confirms the service account has sufficient permissions to read the target data | + +## Troubleshooting + +If a connection test fails: + +- Verify the source hostname, port, and path are correct. +- Confirm the service account credentials have not expired or been rotated. +- Check that network firewalls allow traffic between the Access Analyzer server and the target host. +- For Entra ID, verify the Tenant ID is correct and the app registration has the required API permissions. +- Review [System Logs](/docs/accessanalyzer/1_0/admin/systemlogs) for detailed error messages. + +:::note +Connection tests do not scan data. They only validate that the connection can be established and authenticated. +::: diff --git a/docs/accessanalyzer/1.0/admin/systemlogs.md b/docs/accessanalyzer/1.0/admin/systemlogs.md new file mode 100644 index 0000000000..383d3646d2 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/systemlogs.md @@ -0,0 +1,47 @@ +--- +title: "System Logs" +description: "Viewing and exporting system log data" +sidebar_position: 110 +--- + +# System Logs + +System logs provide visibility into the internal operations of Access Analyzer, including application events, background job processing, and error diagnostics. These logs are distinct from audit logs, which track user actions. + +## Viewing System Logs + +Navigate to **System Logs** in the sidebar to access the log viewer. System logs display application-level events including: + +- Application startup and shutdown events +- Background job execution (scan workers, identity sync) +- Connection errors and retry attempts +- API request errors and exceptions + +## Sidekiq Dashboard + +Access Analyzer uses Sidekiq for background job processing. The Sidekiq dashboard provides real-time monitoring of: + +| View | Description | +|---|---| +| **Queues** | Active job queues and their current depth | +| **Workers** | Currently executing jobs and their runtime | +| **Retries** | Failed jobs scheduled for automatic retry | +| **Dead** | Jobs that have exhausted all retry attempts | +| **Scheduled** | Jobs queued for future execution | + +Access the Sidekiq dashboard from **System Logs** > **Job Monitor**. + +## Log Levels + +System logs are categorized by severity: + +| Level | Description | +|---|---| +| **ERROR** | Failures requiring attention | +| **WARN** | Unexpected conditions that did not cause failures | +| **INFO** | Normal operational events | +| **DEBUG** | Detailed diagnostic output (disabled by default) | + +:::note +Debug-level logging generates significant output and can impact performance. Enable it only for targeted troubleshooting and disable it afterward. +::: diff --git a/docs/accessanalyzer/1.0/admin/users/_category_.json b/docs/accessanalyzer/1.0/admin/users/_category_.json new file mode 100644 index 0000000000..9633707491 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/users/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "User Management", + "position": 20, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/admin/users/overview.md b/docs/accessanalyzer/1.0/admin/users/overview.md new file mode 100644 index 0000000000..74de4204be --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/users/overview.md @@ -0,0 +1,38 @@ +--- +title: "User Management" +description: "Creating and managing user accounts" +sidebar_position: 10 +--- + +# User Management + +Access Analyzer supports multi-user access with role-based permissions. Administrators can create, edit, and deactivate user accounts from the **Users** section of the web interface. + +## Creating a User + +To create a new user: + +1. Navigate to **Users** in the sidebar. +2. Click **Create User**. +3. Enter the required fields: **Username**, **Email**, and **Password**. +4. Assign a [role](/docs/accessanalyzer/1_0/admin/users/roles) (Administrator or Viewer). +5. Click **Save**. + +Passwords are hashed using Argon2id before storage. Users must meet the configured password complexity requirements. + +## Managing Users + +From the users list, administrators can: + +- **Edit** a user to update their email, role, or password. +- **Deactivate** a user to revoke access without deleting the account record. +- **Delete** a user to permanently remove the account. + +:::warning +Deleting a user is irreversible. Consider deactivating accounts instead if you need to preserve audit history. +::: + +## Related Topics + +- [Roles and Permissions](/docs/accessanalyzer/1_0/admin/users/roles) +- [Session Management](/docs/accessanalyzer/1_0/admin/users/sessions) diff --git a/docs/accessanalyzer/1.0/admin/users/roles.md b/docs/accessanalyzer/1.0/admin/users/roles.md new file mode 100644 index 0000000000..9c83c8f400 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/users/roles.md @@ -0,0 +1,36 @@ +--- +title: "Roles and Permissions" +description: "Admin and Viewer role definitions and access levels" +sidebar_position: 20 +--- + +# Roles and Permissions + +Access Analyzer uses a role-based access control model with two built-in roles. Each user is assigned exactly one role at account creation, which determines their access level throughout the application. + +## Role Definitions + +| Capability | Administrator | Viewer | +|---|---|---| +| View dashboards and reports | Yes | Yes | +| View sources, scans, and results | Yes | Yes | +| Create, edit, and delete sources | Yes | No | +| Create, schedule, and run scans | Yes | No | +| Manage service accounts | Yes | No | +| Configure sensitive data rules | Yes | No | +| Manage users and roles | Yes | No | +| Modify application settings | Yes | No | +| View audit logs | Yes | Yes | +| Export audit logs | Yes | No | + +## Administrator + +The **Administrator** role grants full access to all features, including user management, source configuration, scan execution, settings, and audit log exports. At least one administrator account must exist in the system. + +## Viewer + +The **Viewer** role provides read-only access to dashboards, scan results, source listings, and audit logs. Viewers cannot create, modify, or delete any resources. + +:::note +Role assignments can be changed at any time by an administrator through the user edit form. +::: diff --git a/docs/accessanalyzer/1.0/admin/users/sessions.md b/docs/accessanalyzer/1.0/admin/users/sessions.md new file mode 100644 index 0000000000..7af8472d7f --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/users/sessions.md @@ -0,0 +1,35 @@ +--- +title: "Session Management" +description: "Viewing and managing active user sessions" +sidebar_position: 30 +--- + +# Session Management + +Access Analyzer maintains session state for all authenticated users using Redis-backed server-side sessions. Administrators can view and manage active sessions from the **Users** section. + +## Viewing Active Sessions + +Navigate to **Users** > **Sessions** to see a list of all active sessions. The table displays: + +| Column | Description | +|---|---| +| **User** | The username associated with the session | +| **IP Address** | The client IP from which the session was created | +| **Created At** | Timestamp when the session was initiated | +| **Last Active** | Timestamp of the most recent request | +| **Expires At** | When the session will automatically expire based on the configured TTL | + +## Revoking Sessions + +To revoke a session, select the target row and click **Revoke**. The user will be immediately logged out and must re-authenticate. Administrators can also revoke all sessions for a specific user from the user detail page. + +## Session Security + +- Sessions are validated against the originating IP address. If the client IP changes, the session is invalidated. +- Session TTL is configurable in [Settings](/docs/accessanalyzer/1_0/admin/settings/sessionttl). +- Idle sessions expire automatically after the configured timeout period. + +:::warning +Revoking a session takes effect immediately. The affected user will lose access to any in-progress work that has not been saved. +::: diff --git a/docs/accessanalyzer/1.0/connectors/_category_.json b/docs/accessanalyzer/1.0/connectors/_category_.json new file mode 100644 index 0000000000..f7b8ad38d7 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Connectors", + "position": 60, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/connectors/iam/_category_.json b/docs/accessanalyzer/1.0/connectors/iam/_category_.json new file mode 100644 index 0000000000..47506a72c8 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/iam/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "IAM Connectors", + "position": 10, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/connectors/iam/activedirectory/_category_.json b/docs/accessanalyzer/1.0/connectors/iam/activedirectory/_category_.json new file mode 100644 index 0000000000..365d3210fe --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/iam/activedirectory/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Active Directory", + "position": 10, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "connectionsetup" + } +} diff --git a/docs/accessanalyzer/1.0/connectors/iam/activedirectory/connectionsetup.md b/docs/accessanalyzer/1.0/connectors/iam/activedirectory/connectionsetup.md new file mode 100644 index 0000000000..3dbcd27070 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/iam/activedirectory/connectionsetup.md @@ -0,0 +1,47 @@ +--- +title: "Connection Setup" +description: "Configuring the Active Directory LDAP connection" +sidebar_position: 10 +--- + +# Connection Setup + +Configure the Active Directory connector to synchronize users and groups from your on-premises directory. + +## Prerequisites + +- A domain service account with read access to directory objects — see [Active Directory Requirements](/docs/accessanalyzer/1_0/requirements/connectors/activedirectory) +- Network connectivity from the Access Analyzer VM to a domain controller on port 389 (LDAP) or 636 (LDAPS) + +## Create a Service Account + +1. Navigate to **Service Accounts** in the sidebar +2. Click **Add Service Account** +3. Enter a **Name** (for example, `AD Read-Only Service Account`) +4. Select **Username/Password** as the type +5. Enter the **Username** in `DOMAIN\username` or `user@domain.com` format +6. Enter the **Password** +7. Click **Add service account** + +## Add Active Directory as a Source + +1. Navigate to **Configuration** > **Sources** +2. Click **Add Source** +3. Select **IAM Source** as the category +4. Select **Active Directory** as the source type +5. Select the service account created above +6. Enter the **Host** (domain controller hostname or IP) +7. Enter the **Port** (`389` for LDAP, `636` for LDAPS) +8. Enter the **Domain** (for example, `corp.example.com`) +9. Click **Test Connection** to verify connectivity +10. After a successful test, click **Create Source** + +## Test Connection + +The test connection validates: + +- Network connectivity to the domain controller +- LDAP bind with the provided credentials +- Ability to query directory objects + +If the test fails, verify the domain controller is reachable on the specified port and the credentials are correct. diff --git a/docs/accessanalyzer/1.0/connectors/iam/activedirectory/customattributes.md b/docs/accessanalyzer/1.0/connectors/iam/activedirectory/customattributes.md new file mode 100644 index 0000000000..fb620e0bb8 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/iam/activedirectory/customattributes.md @@ -0,0 +1,12 @@ +--- +title: "Custom Attributes" +description: "Collecting custom LDAP attributes" +sidebar_position: 40 +draft: true +--- + +# Custom Attributes + +:::note +Custom LDAP attribute collection is planned for a future release of Access Analyzer. This page will be updated when the feature becomes available. +::: diff --git a/docs/accessanalyzer/1.0/connectors/iam/activedirectory/groupmembership.md b/docs/accessanalyzer/1.0/connectors/iam/activedirectory/groupmembership.md new file mode 100644 index 0000000000..397959033f --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/iam/activedirectory/groupmembership.md @@ -0,0 +1,26 @@ +--- +title: "Group Membership Mapping" +description: "Transitive group membership resolution" +sidebar_position: 30 +--- + +# Group Membership Mapping + +Access Analyzer resolves transitive (nested) group memberships to build a complete picture of effective access. + +## How It Works + +The Active Directory connector collects: + +1. **Direct memberships** — Users and groups that are immediate members of a group +2. **Nested memberships** — Groups that are members of other groups, creating a hierarchy + +Access Analyzer flattens these hierarchies to determine **effective membership** — the complete list of groups a user belongs to, whether directly or through nesting. + +## Impact on Access Analysis + +Effective group memberships are mapped to entitlements discovered by source connector scans, enabling Access Analyzer to show: + +- All groups that grant a user access to a resource +- Whether access comes from direct or nested group membership +- Overly permissive access through deeply nested group chains diff --git a/docs/accessanalyzer/1.0/connectors/iam/activedirectory/usergroupsync.md b/docs/accessanalyzer/1.0/connectors/iam/activedirectory/usergroupsync.md new file mode 100644 index 0000000000..3be2c6e33e --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/iam/activedirectory/usergroupsync.md @@ -0,0 +1,30 @@ +--- +title: "User and Group Sync" +description: "Synchronizing users and groups from Active Directory" +sidebar_position: 20 +--- + +# User and Group Sync + +The Active Directory connector performs a full synchronization of users, groups, and group memberships. + +## What Gets Synchronized + +| Object Type | Data Collected | +| --- | --- | +| **Users** | Display name, SAM account name, UPN, email, distinguished name, enabled status | +| **Groups** | Group name, type (security/distribution), scope (domain local/global/universal), distinguished name | +| **Group memberships** | Direct and nested membership relationships | + +## Running a Sync + +1. Navigate to **Configuration** > **Scans** +2. Create or select a scan configured for the Active Directory source +3. Run the scan — the connector performs a full sync on each execution + +## Sync Behavior + +- Each sync is a **full synchronization** — all users, groups, and memberships are collected +- The connector uses LDAP3 for directory queries +- Duration depends on directory size (number of users and groups) +- Results are stored in the Access Analyzer database and used for identity-to-entitlement mapping diff --git a/docs/accessanalyzer/1.0/connectors/iam/entraid/_category_.json b/docs/accessanalyzer/1.0/connectors/iam/entraid/_category_.json new file mode 100644 index 0000000000..d1dd3ba163 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/iam/entraid/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Entra ID", + "position": 20, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "appregistration" + } +} diff --git a/docs/accessanalyzer/1.0/connectors/iam/entraid/appregistration.md b/docs/accessanalyzer/1.0/connectors/iam/entraid/appregistration.md new file mode 100644 index 0000000000..cdc2d7edef --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/iam/entraid/appregistration.md @@ -0,0 +1,74 @@ +--- +title: "App Registration and Permissions" +description: "Azure AD app registration and API permissions for Entra ID" +sidebar_position: 10 +--- + +# App Registration and Permissions + +The Entra ID connector uses an Azure AD app registration with OAuth2 client credentials for authentication. You need to create an app registration in Azure and then add its credentials as a service account in Access Analyzer. + +## Create an App Registration + +1. Sign in to the [Azure portal](https://portal.azure.com) +2. Navigate to **Microsoft Entra ID** > **App registrations** +3. Click **New registration** +4. Enter a name (for example, `Netwrix Access Analyzer - Entra ID`) +5. Leave the redirect URI blank +6. Click **Register** + +## Configure API Permissions + +1. In the app registration, go to **API permissions** +2. Click **Add a permission** > **Microsoft Graph** > **Application permissions** +3. Add the following permissions: + - `User.Read.All` + - `Group.Read.All` +4. Click **Grant admin consent** for the permissions + +## Create a Client Secret + +1. Go to **Certificates & secrets** +2. Click **New client secret** +3. Enter a description and expiration period +4. Click **Add** +5. Copy the **Value** immediately — it is not shown again + +## Add Entra ID as a Source in Access Analyzer + +Entra ID sources are created through the **Connect Source** wizard, which guides you through a 3-step process: + +### Step 1 — Select Source Type + +1. Navigate to **Configuration** > **Sources** in Access Analyzer +2. Click **Connect Source** to open the wizard drawer +3. Select **Entra ID** from the source type cards +4. Click **Next** + +### Step 2 — Configure Entra ID + +1. Enter a **Source Group Name** (for example, `Corporate Entra ID`) +2. Select or create a **Service Account**: + - Click **+ Create New Account** to add a new Entra ID service account + - Enter the **Client ID** (Application ID from Azure) and **Client Secret** + - Or select an existing Entra ID service account from the dropdown +3. Enter the **Tenant ID** — this is the Azure AD directory ID in UUID format (for example, `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`) +4. Optionally click **Test Connection** to verify OAuth2 authentication + +:::note +The test connection validates that Access Analyzer can authenticate to the Microsoft Graph API with the provided credentials. Testing is optional — you can proceed without testing. +::: + +### Step 3 — Set Up a Scan + +1. The **Users, Groups and Roles** scan is automatically enabled (cannot be disabled) +2. Configure any additional sync options (for example, **Sync Sensitivity Labels**) +3. Choose when to run the first scan: now, at a scheduled time, or on a recurring schedule +4. Click **Complete Setup** + +After setup, the source group is created and the scan runs according to your selected schedule. + +## Related Topics + +- [User and Group Sync](/docs/accessanalyzer/1_0/connectors/iam/entraid/usergroupsync) — What data is synchronized +- [Entra ID Requirements](/docs/accessanalyzer/1_0/requirements/connectors/entraid) — Permissions and prerequisites diff --git a/docs/accessanalyzer/1.0/connectors/iam/entraid/certificateauth.md b/docs/accessanalyzer/1.0/connectors/iam/entraid/certificateauth.md new file mode 100644 index 0000000000..a92d6d15ab --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/iam/entraid/certificateauth.md @@ -0,0 +1,12 @@ +--- +title: "Certificate-Based Authentication" +description: "Configuring certificate authentication for Entra ID" +sidebar_position: 30 +draft: true +--- + +# Certificate-Based Authentication + +:::note +Certificate-based authentication for Entra ID is planned for a future release. In v1.0, the Entra ID connector uses OAuth2 client credentials (client secret) authentication. See [App Registration and Permissions](/docs/accessanalyzer/1_0/connectors/iam/entraid/appregistration). +::: diff --git a/docs/accessanalyzer/1.0/connectors/iam/entraid/usergroupsync.md b/docs/accessanalyzer/1.0/connectors/iam/entraid/usergroupsync.md new file mode 100644 index 0000000000..73f1d48a42 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/iam/entraid/usergroupsync.md @@ -0,0 +1,47 @@ +--- +title: "User and Group Sync" +description: "Synchronizing users, groups, and roles from Entra ID" +sidebar_position: 20 +--- + +# User and Group Sync + +The Entra ID connector synchronizes users, groups, and roles from your Azure AD tenant into Access Analyzer. This data is used for identity mapping and entitlement analysis across your data sources. + +## What Gets Synchronized + +| Data | Description | +| --- | --- | +| **Users** | All user accounts in the tenant, including display name, UPN, and account status | +| **Groups** | Security groups and Microsoft 365 groups, including membership | +| **Roles** | Directory roles assigned to users and groups | +| **Sensitivity Labels** | Microsoft Purview sensitivity labels (optional — see [Sync Options](#sync-options) below) | + +## How It Works + +When you create an Entra ID source group through the [Connect Source wizard](/docs/accessanalyzer/1_0/gettingstarted/firstscan/addingsource), a **Users, Groups and Roles** scan is automatically configured. This scan is always enabled and cannot be disabled — it runs every time the Entra ID source is scanned. + +The connector authenticates using OAuth2 client credentials and calls the Microsoft Graph API to retrieve identity data from the specified tenant. + +## Sync Options + +During scan setup (Step 3 of the wizard), additional sync options may be available depending on the source type metadata configured on the backend. For example: + +- **Sync Sensitivity Labels** — When enabled, the connector also retrieves Microsoft Purview sensitivity labels assigned to users and groups + +These options appear as toggle switches below the scan type selector on the scan setup page. + +## Scan Scheduling + +The Users, Groups and Roles scan supports three scheduling modes: + +| Mode | Description | +| --- | --- | +| **Run scan now** | Execute immediately after setup completes | +| **Run scan at** | Schedule for a specific date and time | +| **Advanced scheduling** | Configure a recurring cron schedule | + +## Related Topics + +- [App Registration and Permissions](/docs/accessanalyzer/1_0/connectors/iam/entraid/appregistration) — Azure AD setup requirements +- [Entra ID Requirements](/docs/accessanalyzer/1_0/requirements/connectors/entraid) — Permissions and prerequisites diff --git a/docs/accessanalyzer/1.0/connectors/iam/localgroups/_category_.json b/docs/accessanalyzer/1.0/connectors/iam/localgroups/_category_.json new file mode 100644 index 0000000000..19a04b0aec --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/iam/localgroups/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Local Groups", + "position": 30, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "powershellsetup" + } +} diff --git a/docs/accessanalyzer/1.0/connectors/iam/localgroups/powershellsetup.md b/docs/accessanalyzer/1.0/connectors/iam/localgroups/powershellsetup.md new file mode 100644 index 0000000000..0144b61557 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/iam/localgroups/powershellsetup.md @@ -0,0 +1,52 @@ +--- +title: "PowerShell Remoting Setup" +description: "Configuring WinRM and PowerShell Remoting for Local Groups collection" +sidebar_position: 10 +--- + +# PowerShell Remoting Setup + +The Local Groups connector uses PowerShell Remoting (WinRM) to enumerate local users and groups on Windows machines. + +## Prerequisites + +- WinRM must be enabled on each target machine +- A service account with local administrator access or membership in the Remote Management Users group +- Network connectivity from Access Analyzer to target machines on port 5985 (HTTP) or 5986 (HTTPS) + +## Enable WinRM on Target Machines + +### Single Machine + +Run the following command in an elevated PowerShell prompt: + +```powershell +Enable-PSRemoting -Force +``` + +### Domain-Wide via Group Policy + +1. Open **Group Policy Management** +2. Navigate to **Computer Configuration** > **Administrative Templates** > **Windows Components** > **Windows Remote Management (WinRM)** > **WinRM Service** +3. Enable **Allow remote server management through WinRM** +4. Set the IPv4/IPv6 filter to `*` or specific IP ranges + +## Create a Service Account + +1. Navigate to **Service Accounts** in Access Analyzer +2. Click **Add Service Account** +3. Enter a **Name** (for example, `Local Groups - WinRM`) +4. Select **Username/Password** as the type +5. Enter the **Username** in `MACHINE\username` or `DOMAIN\username` format +6. Enter the **Password** +7. Click **Add service account** + +## Add Local Groups as a Source + +1. Navigate to **Configuration** > **Sources** +2. Click **Add Source** > **IAM Source** > **Local Groups** +3. Select the service account +4. Enter the **Host** (target machine hostname or IP) +5. Enter the **Port** (`5985` for HTTP, `5986` for HTTPS) +6. Click **Test Connection** +7. Click **Create Source** diff --git a/docs/accessanalyzer/1.0/connectors/iam/localgroups/usergroupcollection.md b/docs/accessanalyzer/1.0/connectors/iam/localgroups/usergroupcollection.md new file mode 100644 index 0000000000..2fed900d2b --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/iam/localgroups/usergroupcollection.md @@ -0,0 +1,40 @@ +--- +title: "Local User and Group Collection" +description: "Collecting local users and groups from target machines" +sidebar_position: 20 +--- + +# Local User and Group Collection + +The Local Groups connector collects local users, local groups, and group memberships from Windows machines via PowerShell Remoting. + +## What Gets Collected + +| Object Type | Data Collected | +| --- | --- | +| **Local users** | Username, full name, description, enabled status, last logon | +| **Local groups** | Group name, description, type | +| **Group memberships** | Local group members (local users and domain accounts/groups) | + +## Running a Sync + +1. Navigate to **Configuration** > **Scans** +2. Create or select a scan configured for the Local Groups source +3. Run the scan — the connector performs a sync on each execution + +## How It Works + +The connector: + +1. Establishes a WinRM session to the target machine +2. Executes PowerShell commands to enumerate local users and groups +3. Collects group membership information, including domain accounts that are members of local groups +4. Returns results to the Core API for storage and analysis + +## Use Cases + +Local group collection is useful for: + +- Identifying domain accounts with local administrator access +- Mapping local group memberships that grant file share permissions +- Detecting overly permissive local group configurations diff --git a/docs/accessanalyzer/1.0/connectors/iam/overview.md b/docs/accessanalyzer/1.0/connectors/iam/overview.md new file mode 100644 index 0000000000..e0f373519b --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/iam/overview.md @@ -0,0 +1,21 @@ +--- +title: "IAM Connectors" +description: "Identity and access management connectors" +sidebar_position: 1 +--- + +# IAM Connectors + +IAM (Identity and Access Management) connectors synchronize identity data — users, groups, and group memberships — from identity providers into Access Analyzer. This data is used to map who has access to what across your data sources. + +## Available IAM Connectors + +| Connector | Identity Provider | Operations | Credential Type | +| --- | --- | --- | --- | +| [Active Directory](/docs/accessanalyzer/1_0/connectors/iam/activedirectory/connectionsetup) | On-premises AD | Test connection, Full sync | Username / Password | +| [Entra ID](/docs/accessanalyzer/1_0/connectors/iam/entraid/appregistration) | Microsoft Entra ID | Test connection only | OAuth2 Client Credentials | +| [Local Groups](/docs/accessanalyzer/1_0/connectors/iam/localgroups/powershellsetup) | Windows local accounts | Test connection, Sync | Username / Password | + +:::note +The Entra ID connector in v1.0 supports test connection only. Full identity synchronization will be available in a future release. +::: diff --git a/docs/accessanalyzer/1.0/connectors/overview.md b/docs/accessanalyzer/1.0/connectors/overview.md new file mode 100644 index 0000000000..e3c68accb8 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/overview.md @@ -0,0 +1,42 @@ +--- +title: "Connectors" +description: "Connector architecture, types, and lifecycle" +sidebar_position: 1 +--- + +# Connectors + +Connectors are the components that communicate with external data sources and identity providers on behalf of Access Analyzer. Each connector handles authentication, data collection, and state management for its target system. + +## Connector Types + +| Category | Purpose | Connectors | +| --- | --- | --- | +| **IAM Connectors** | Synchronize identities (users, groups, memberships) from identity providers | [Active Directory](/docs/accessanalyzer/1_0/connectors/iam/activedirectory/connectionsetup), [Entra ID](/docs/accessanalyzer/1_0/connectors/iam/entraid/appregistration), [Local Groups](/docs/accessanalyzer/1_0/connectors/iam/localgroups/powershellsetup) | +| **Source Connectors** | Scan data repositories for files, permissions, and content | [CIFS/SMB](/docs/accessanalyzer/1_0/connectors/source/cifs/connectionconfig), [SharePoint Online](/docs/accessanalyzer/1_0/connectors/source/sharepointonline/connectionconfig) | + +## Connector Operations + +| Operation | Description | +| --- | --- | +| **Test connection** | Validates credentials and network connectivity | +| **Access scan** | Enumerates files, folders, and permissions on a data source | +| **Sync** | Synchronizes users, groups, and memberships from an identity provider | +| **Get object** | Retrieves specific objects or metadata from the target system | + +## Connector Execution + +Connectors run as Kubernetes Jobs managed by the Connector API. When a scan or sync is triggered: + +1. The Core API creates a scan execution record +2. The Connector API launches a Kubernetes Job with the appropriate connector +3. The connector authenticates using the associated service account +4. Data is collected and sent back to the Core API for processing +5. The job completes and reports its final status + +## State Management + +| Connector | Pause/Resume | +| --- | --- | +| CIFS/SMB | Supported | +| All others | Not supported | diff --git a/docs/accessanalyzer/1.0/connectors/source/_category_.json b/docs/accessanalyzer/1.0/connectors/source/_category_.json new file mode 100644 index 0000000000..895acef0a9 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/source/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Source Connectors", + "position": 20, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/connectors/source/cifs/_category_.json b/docs/accessanalyzer/1.0/connectors/source/cifs/_category_.json new file mode 100644 index 0000000000..6e8930174e --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/source/cifs/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "CIFS / SMB File Shares", + "position": 10, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "connectionconfig" + } +} diff --git a/docs/accessanalyzer/1.0/connectors/source/cifs/connectionconfig.md b/docs/accessanalyzer/1.0/connectors/source/cifs/connectionconfig.md new file mode 100644 index 0000000000..433e9c371a --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/source/cifs/connectionconfig.md @@ -0,0 +1,79 @@ +--- +title: "Connection Configuration" +description: "Configuring CIFS/SMB connection parameters" +sidebar_position: 10 +--- + +# Connection Configuration + +Configure the CIFS/SMB connector to scan Windows file shares for files, folders, and access permissions. File server sources are created through the **Connect Source** wizard, which supports adding multiple servers in a single source group. + +## Prerequisites + +- A service account with read access to target shares — see [CIFS Requirements](/docs/accessanalyzer/1_0/requirements/connectors/cifs) +- Network connectivity from Access Analyzer to each file server on port 445 + +## Creating a File Server Source Group + +File server sources are created through the 3-step **Connect Source** wizard: + +### Step 1 — Select Source Type + +1. Navigate to **Configuration** > **Sources** +2. Click **Connect Source** to open the wizard drawer +3. Select **File Server** from the source type cards +4. Click **Next** + +### Step 2 — Configure File Server + +1. Enter a **Source Group Name** (for example, `Finance File Servers`) +2. Select or create a **Service Account**: + - Click **+ Create New Account** to add a new username/password account + - Or select an existing service account from the dropdown +3. Optionally enter a **Domain** name (for example, `company.local`). The domain is applied to all servers in the group. + +### Adding File Servers + +Click **+ Add** or click the empty state area to begin adding servers: + +1. Select **Add Manually** (CSV import is planned for a future release) +2. In the manual entry form, enter one or more server names or IP addresses: + - Type multiple entries separated by commas, or press **Enter** after each one + - For example: `fs01, fs02, fs03` +3. Set the **Port** (default: `445`) +4. Click **Add [N] file servers** +5. Review the added servers in the table — server names are editable inline +6. Click **Done** to return to the configuration screen + +The file servers table shows each server's name, connection status, and a delete button. + +### Test Connection + +After adding servers and selecting a service account: + +1. Click **Test Connection** +2. All servers are tested in parallel +3. Each server shows its status: **Connected** (green), **Failed** (red), or **Testing** (spinner) +4. A summary toast displays the results (for example, "All 3 connections successful" or "1 of 3 failed") + +:::note +Testing is optional and non-blocking — you can proceed to the next step regardless of test results. +::: + +### Connection Parameters + +Each file server in the group uses the following connection parameters: + +| Parameter | Description | Default | +| --- | --- | --- | +| **Host** | File server hostname or IP address | — | +| **Port** | SMB port | `445` | +| **Domain** | Domain name (set at the group level) | — | + +## Supported Protocols + +The connector supports SMBv2 and SMBv3. SMBv1 is not supported due to security vulnerabilities. + +## Next Steps + +After configuring servers, click **Next** to proceed to [scan setup](/docs/accessanalyzer/1_0/gettingstarted/firstscan/configuringscan), where you configure access scan options, share filtering, and scheduling. diff --git a/docs/accessanalyzer/1.0/connectors/source/cifs/filevssharelevel.md b/docs/accessanalyzer/1.0/connectors/source/cifs/filevssharelevel.md new file mode 100644 index 0000000000..e3e596a606 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/source/cifs/filevssharelevel.md @@ -0,0 +1,53 @@ +--- +title: "File-Level vs Share-Level Permissions" +description: "Understanding file-level and share-level permission scanning" +sidebar_position: 50 +--- + +# File-Level vs Share-Level Permissions + +Windows file shares have two layers of access control: **share-level permissions** and **NTFS file-level permissions**. The effective access for a user is the most restrictive combination of both. + +## Share-Level Permissions + +Share-level permissions are set on the share itself and apply to all network access: + +- **Read** — View files and subfolders +- **Change** — Read, add, modify, and delete files +- **Full Control** — All Change permissions plus the ability to modify share permissions + +## NTFS File-Level Permissions + +NTFS permissions are set on individual files and folders and provide granular control: + +- **Read** — View file contents and attributes +- **Write** — Create files and write data +- **Modify** — Read, write, and delete +- **Full Control** — All permissions including permission changes and ownership + +## Effective Access + +The effective access for a user connecting over the network is determined by the **intersection** (most restrictive) of share-level and NTFS permissions. + +For example: +- Share permission: **Full Control** +- NTFS permission: **Read** +- Effective access: **Read** + +## Enabling File-Level Permission Scanning + +By default, Access Analyzer scans share-level permissions only. To include file-level (NTFS) permission data: + +1. During source group creation, proceed to Step 3 (scan setup) +2. Enable the **Access** scan type +3. In the access scan options, check **Include file-level permission data in scan results** + +When enabled, the connector reads the NTFS security descriptor for each file and folder in addition to the share-level ACL. This provides more detailed access path analysis but increases scan duration. + +:::note +File-level permission scanning is disabled by default because it significantly increases scan time on large file servers. Enable it when you need detailed per-file permission analysis. +::: + +## What Access Analyzer Scans + +The CIFS/SMB connector collects NTFS permissions at the file and folder level. Combined with share-level permission data, Access Analyzer reports the effective access path from user to file. diff --git a/docs/accessanalyzer/1.0/connectors/source/cifs/ntfspermissions.md b/docs/accessanalyzer/1.0/connectors/source/cifs/ntfspermissions.md new file mode 100644 index 0000000000..6b14bc1b67 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/source/cifs/ntfspermissions.md @@ -0,0 +1,33 @@ +--- +title: "NTFS Permission Scanning" +description: "Scanning NTFS access control lists" +sidebar_position: 30 +--- + +# NTFS Permission Scanning + +The CIFS/SMB connector reads NTFS access control lists (ACLs) on files and folders to identify who has access and what level of access they hold. + +## What Gets Collected + +| Data | Description | +| --- | --- | +| **ACL entries** | Each access control entry (ACE) on a file or folder, including the principal (user or group), access type (allow/deny), and permission level | +| **Permission types** | Read, Write, Modify, Full Control, and other standard NTFS permissions | +| **Inheritance** | Whether permissions are inherited from a parent folder or explicitly set | +| **Owner** | The owner of each file or folder | + +## How It Works + +1. The connector traverses the folder hierarchy on each share +2. For each file and folder, it reads the NTFS security descriptor +3. ACL entries are parsed and stored in the Access Analyzer database +4. Identities referenced in ACLs are matched to synced identities from IAM connectors + +## Access Path Analysis + +By combining NTFS permissions with identity data from Active Directory or Local Groups, Access Analyzer builds **access paths** that show: + +- Which users and groups have access to each file or folder +- Whether access is granted directly or through nested group membership +- Which permissions are explicitly set versus inherited diff --git a/docs/accessanalyzer/1.0/connectors/source/cifs/scandepthworkers.md b/docs/accessanalyzer/1.0/connectors/source/cifs/scandepthworkers.md new file mode 100644 index 0000000000..b83787d563 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/source/cifs/scandepthworkers.md @@ -0,0 +1,54 @@ +--- +title: "Scan Depth and Worker Configuration" +description: "Configuring recursion depth and concurrent workers" +sidebar_position: 40 +--- + +# Scan Depth and Worker Configuration + +The CIFS/SMB connector supports configurable scan depth and concurrent worker threads to balance thoroughness with performance. These settings are configured in Step 3 (scan setup) of the Connect Source wizard when the **Access** scan option is enabled. + +## Scan Depth + +Scan depth controls how many levels of subdirectories the connector traverses within each share. + +| Setting | Description | +| --- | --- | +| **Default** | 50 levels deep | +| **Custom** | Set to any positive integer | + +The default depth of 50 covers the vast majority of file server hierarchies. Increase this value only if your environment has deeply nested folder structures that exceed 50 levels. + +:::note +Setting scan depth to a very high number does not significantly impact performance if the actual folder hierarchy is shallower — the connector stops when there are no more subdirectories to traverse. +::: + +## Worker Threads + +Worker threads control how many directories are scanned concurrently. More threads mean faster scans but higher load on the file server. + +| Setting | Description | +| --- | --- | +| **Default** | 3 concurrent workers | +| **Range** | 1 to 20 workers | + +Guidelines for choosing a worker count: + +| Workers | Use Case | +| --- | --- | +| **1–3** | Conservative scanning with minimal file server impact (default) | +| **5–10** | Balanced performance for most environments | +| **10–20** | Maximum parallelism for large file servers with high I/O capacity | + +:::warning +Increasing worker count improves scan speed but also increases load on the file server. Start with the default of 3 and increase gradually based on file server capacity and observed scan duration. +::: + +## Configuration Location + +Both settings are found in the **Access scan options** section of the scan setup step, which appears when the **Access** scan type is enabled during source group creation. + +## Related Topics + +- [Share Enumeration and Filtering](/docs/accessanalyzer/1_0/connectors/source/cifs/shareenumeration) — Controlling which shares are scanned +- [File-Level vs Share-Level Permissions](/docs/accessanalyzer/1_0/connectors/source/cifs/filevssharelevel) — Permission scanning granularity diff --git a/docs/accessanalyzer/1.0/connectors/source/cifs/shareenumeration.md b/docs/accessanalyzer/1.0/connectors/source/cifs/shareenumeration.md new file mode 100644 index 0000000000..9bcb80a771 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/source/cifs/shareenumeration.md @@ -0,0 +1,53 @@ +--- +title: "Share Enumeration and Filtering" +description: "Discovering and filtering network shares" +sidebar_position: 20 +--- + +# Share Enumeration and Filtering + +When scanning a CIFS/SMB source, the connector discovers all available shares on the target file server. You can include or exclude specific shares, and optionally enumerate hidden shares. + +## How Share Discovery Works + +The connector enumerates all SMB shares exposed by the file server. Each share is listed with its name and path. + +## Share Filtering + +Share filtering is configured in Step 3 (scan setup) of the Connect Source wizard when the **Access** scan option is enabled. Two filtering controls are available: + +### Include Shares + +Control which shares are scanned: + +| Mode | Behavior | +| --- | --- | +| **All shares** (default) | Scan every discovered share on the file server | +| **Custom selection** | Only scan shares you explicitly specify | + +When **Custom selection** is chosen, a text field appears where you enter share names separated by commas (for example, `share1, share2, share3`). + +### Exclude Shares + +Optionally specify shares to skip during scanning. Enter share names separated by commas in the exclude field (for example, `admin$, ipc$`). Excluded shares are never scanned, even if they match the include filter. + +## Hidden Shares + +Windows hidden shares (shares whose names end with `$`) are not enumerated by default. You can enable automatic discovery of hidden shares: + +1. In the scan setup step, check **Automatically enumerate and scan hidden shares** +2. When enabled, the connector discovers and scans hidden shares alongside regular shares +3. A predefined list of default exclusions is applied automatically + +### Excluding Hidden Shares + +When hidden share collection is enabled, an additional **Exclude Hidden Shares** field appears. Enter hidden share names to exclude from auto-enumeration (for example, `ADMIN$, C$, IPC$`). + +:::info +Filtering shares reduces scan duration and focuses results on the most relevant data repositories. Exclude administrative shares (like `ADMIN$` and `IPC$`) unless you specifically need to audit their permissions. +::: + +## Related Topics + +- [Connection Configuration](/docs/accessanalyzer/1_0/connectors/source/cifs/connectionconfig) — Setting up file server connections +- [Scan Depth and Worker Configuration](/docs/accessanalyzer/1_0/connectors/source/cifs/scandepthworkers) — Controlling scan thoroughness diff --git a/docs/accessanalyzer/1.0/connectors/source/overview.md b/docs/accessanalyzer/1.0/connectors/source/overview.md new file mode 100644 index 0000000000..90620d8484 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/source/overview.md @@ -0,0 +1,23 @@ +--- +title: "Source Connectors" +description: "Data source connectors for file and cloud scanning" +sidebar_position: 1 +--- + +# Source Connectors + +Source connectors scan data repositories to discover files, folders, access permissions, and content. Results are used to identify overly permissive access and detect sensitive data. + +## Available Source Connectors + +| Connector | Data Source | Operations | Credential Type | +| --- | --- | --- | --- | +| [CIFS / SMB](/docs/accessanalyzer/1_0/connectors/source/cifs/connectionconfig) | Windows file shares | Test connection, Access scan, Get object | Username / Password | +| [SharePoint Online](/docs/accessanalyzer/1_0/connectors/source/sharepointonline/connectionconfig) | SharePoint Online sites | Test connection, Access scan, Get object | Certificate | + +## Scan Types + +| Scan Type | Description | +| --- | --- | +| **Access scan** | Enumerates file structure and access permissions | +| **Sensitive data scan** | Classifies file content against detection patterns | diff --git a/docs/accessanalyzer/1.0/connectors/source/sharepointonline/_category_.json b/docs/accessanalyzer/1.0/connectors/source/sharepointonline/_category_.json new file mode 100644 index 0000000000..4646f7123f --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/source/sharepointonline/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "SharePoint Online", + "position": 20, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "connectionconfig" + } +} diff --git a/docs/accessanalyzer/1.0/connectors/source/sharepointonline/connectionconfig.md b/docs/accessanalyzer/1.0/connectors/source/sharepointonline/connectionconfig.md new file mode 100644 index 0000000000..90bd541e78 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/source/sharepointonline/connectionconfig.md @@ -0,0 +1,44 @@ +--- +title: "Connection Configuration" +description: "Configuring SharePoint Online connection parameters" +sidebar_position: 10 +--- + +# Connection Configuration + +Configure the SharePoint Online connector to scan SharePoint sites using the Microsoft Graph API with certificate-based authentication. + +## Prerequisites + +- An Azure AD app registration with `Sites.Read.All` permission — see [SharePoint Online Requirements](/docs/accessanalyzer/1_0/requirements/connectors/sharepointonline) +- A certificate (public/private key pair) uploaded to the app registration +- Network connectivity from Access Analyzer to Microsoft Graph API (port 443) + +## Create a Service Account + +1. Navigate to **Service Accounts** in the sidebar +2. Click **Add Service Account** +3. Enter a **Name** (for example, `SharePoint Online - Graph API`) +4. Select **Certificate** as the type +5. Enter the **Client ID** (Application ID from the Azure app registration) +6. Enter the **Tenant ID** (Directory ID) +7. Upload the **Certificate** (private key `.pem` file) +8. Click **Add service account** + +## Add a SharePoint Online Source + +1. Navigate to **Configuration** > **Sources** +2. Click **Add Source** +3. Select **Data Source** as the category +4. Select **SharePoint Online** as the source type +5. Select the certificate-based service account created above +6. Click **Test Connection** to verify Graph API connectivity +7. After a successful test, click **Create Source** + +## Test Connection + +The test connection validates: + +- Certificate authentication with the Microsoft identity platform +- Graph API access with the configured permissions +- Ability to enumerate SharePoint sites diff --git a/docs/accessanalyzer/1.0/connectors/source/sharepointonline/permissionsharinglinks.md b/docs/accessanalyzer/1.0/connectors/source/sharepointonline/permissionsharinglinks.md new file mode 100644 index 0000000000..18a311c439 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/source/sharepointonline/permissionsharinglinks.md @@ -0,0 +1,35 @@ +--- +title: "Permission and Sharing Link Analysis" +description: "Analyzing SharePoint permissions and external sharing links" +sidebar_position: 30 +--- + +# Permission and Sharing Link Analysis + +The SharePoint Online connector collects permission data from SharePoint sites to identify who has access to documents and whether content is shared externally. + +## What Gets Collected + +| Data | Description | +| --- | --- | +| **Site permissions** | Users and groups with access to the site, including permission levels (Full Control, Edit, Read) | +| **Library permissions** | Custom permissions set at the document library level | +| **Item-level permissions** | Unique permissions on individual files or folders (broken inheritance) | +| **Sharing links** | Anonymous links, organization-wide links, and people-specific sharing links | + +## Sharing Link Types + +| Link Type | Description | Risk Level | +| --- | --- | --- | +| **Anyone** | Anonymous access — no authentication required | High | +| **Organization** | Anyone in the organization can access | Medium | +| **Specific people** | Only named users can access | Low | + +## How It Helps + +Permission and sharing link analysis enables you to: + +- Identify documents shared externally via anonymous links +- Find overly permissive site-level access +- Detect broken permission inheritance on sensitive documents +- Review sharing link expiration and access levels diff --git a/docs/accessanalyzer/1.0/connectors/source/sharepointonline/scanningspecificsites.md b/docs/accessanalyzer/1.0/connectors/source/sharepointonline/scanningspecificsites.md new file mode 100644 index 0000000000..e4203c5679 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/source/sharepointonline/scanningspecificsites.md @@ -0,0 +1,30 @@ +--- +title: "Scanning Specific Sites" +description: "Targeting specific SharePoint sites for scanning" +sidebar_position: 40 +--- + +# Scanning Specific Sites + +By default, the SharePoint Online connector scans all sites accessible to the configured app registration. You can narrow the scope by including or excluding specific sites. + +## Configuring Site Filters + +Site filtering is configured during scan creation in the **Configure Details** step: + +1. Navigate to **Configuration** > **Scans** +2. Create a new scan for the SharePoint Online source +3. In the **Configure Details** step, set site include or exclude filters + +## Filter Options + +| Option | Behavior | +| --- | --- | +| **Include specific sites** | Only scan the listed sites | +| **Exclude specific sites** | Scan all sites except those listed | + +## Use Cases + +- **Compliance scanning** — Scan only sites that contain regulated data (HR, Finance, Legal) +- **Incremental rollout** — Start with a subset of sites and expand over time +- **Performance** — Reduce scan duration by excluding large, low-priority sites diff --git a/docs/accessanalyzer/1.0/connectors/source/sharepointonline/sitelibraryenum.md b/docs/accessanalyzer/1.0/connectors/source/sharepointonline/sitelibraryenum.md new file mode 100644 index 0000000000..62a46f11d3 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/source/sharepointonline/sitelibraryenum.md @@ -0,0 +1,29 @@ +--- +title: "Site and Library Enumeration" +description: "Discovering SharePoint sites and document libraries" +sidebar_position: 20 +--- + +# Site and Library Enumeration + +The SharePoint Online connector discovers SharePoint sites, document libraries, and their contents through the Microsoft Graph API. + +## What Gets Discovered + +| Object Type | Description | +| --- | --- | +| **Sites** | All SharePoint Online sites accessible to the app registration | +| **Document libraries** | Libraries within each site containing files and folders | +| **Files and folders** | Individual items with metadata (name, size, modified date, author) | + +## How It Works + +1. The connector authenticates with the Graph API using the configured certificate +2. Sites are enumerated based on the app registration's permissions (`Sites.Read.All`) +3. For each site, document libraries are discovered +4. Files and folders within each library are traversed and cataloged +5. Results are sent to the Core API for storage and analysis + +## Site Filtering + +You can control which sites are scanned using include/exclude filters. See [Scanning Specific Sites](/docs/accessanalyzer/1_0/connectors/source/sharepointonline/scanningspecificsites) for details. diff --git a/docs/accessanalyzer/1.0/dashboards/_category_.json b/docs/accessanalyzer/1.0/dashboards/_category_.json new file mode 100644 index 0000000000..4795b98214 --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Dashboards and Reports", + "position": 80, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/dashboards/activedirectory.md b/docs/accessanalyzer/1.0/dashboards/activedirectory.md new file mode 100644 index 0000000000..0a72e8f46e --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards/activedirectory.md @@ -0,0 +1,8 @@ +--- +title: "Active Directory Dashboard" +description: "Active Directory identity and access insights" +sidebar_position: 20 +draft: true +--- + +# Active Directory Dashboard diff --git a/docs/accessanalyzer/1.0/dashboards/copilotreadiness.md b/docs/accessanalyzer/1.0/dashboards/copilotreadiness.md new file mode 100644 index 0000000000..ea7b3647a0 --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards/copilotreadiness.md @@ -0,0 +1,8 @@ +--- +title: "Copilot Readiness Dashboard" +description: "Microsoft 365 Copilot readiness assessment" +sidebar_position: 50 +draft: true +--- + +# Copilot Readiness Dashboard diff --git a/docs/accessanalyzer/1.0/dashboards/datasecurity.md b/docs/accessanalyzer/1.0/dashboards/datasecurity.md new file mode 100644 index 0000000000..a9db5d2e47 --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards/datasecurity.md @@ -0,0 +1,8 @@ +--- +title: "Data Security Dashboard" +description: "Data security posture and risk summary" +sidebar_position: 40 +draft: true +--- + +# Data Security Dashboard diff --git a/docs/accessanalyzer/1.0/dashboards/entraid.md b/docs/accessanalyzer/1.0/dashboards/entraid.md new file mode 100644 index 0000000000..c2f2ebf0c2 --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards/entraid.md @@ -0,0 +1,8 @@ +--- +title: "Entra ID Dashboard" +description: "Entra ID identity and access insights" +sidebar_position: 30 +draft: true +--- + +# Entra ID Dashboard diff --git a/docs/accessanalyzer/1.0/dashboards/metabase/_category_.json b/docs/accessanalyzer/1.0/dashboards/metabase/_category_.json new file mode 100644 index 0000000000..af130ea1f5 --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards/metabase/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Metabase Reports", + "position": 60, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "accessingreports" + } +} diff --git a/docs/accessanalyzer/1.0/dashboards/metabase/accessingreports.md b/docs/accessanalyzer/1.0/dashboards/metabase/accessingreports.md new file mode 100644 index 0000000000..c9919abbcc --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards/metabase/accessingreports.md @@ -0,0 +1,36 @@ +--- +title: "Accessing Embedded Reports" +description: "Using Metabase embedded reports in Access Analyzer" +sidebar_position: 10 +--- + +# Accessing Embedded Reports + +Access Analyzer embeds Metabase reports directly into the application interface. You can view, filter, and interact with reports without leaving the platform. + +## Opening a Report + +1. Navigate to the **Dashboards** section in the left navigation menu. +2. Select a dashboard from the list of available dashboards (for example, **Data Security Dashboard**). +3. The embedded Metabase report loads within the Access Analyzer interface. + +## Authentication + +Report access uses JWT-based single sign-on between the Access Analyzer Core API and Metabase. No separate Metabase credentials are required. Your Access Analyzer user permissions determine which dashboards and data you can view. + +## Interacting with Reports + +Once a report is loaded, you can: + +- **Apply filters** — Use the filter controls at the top of the dashboard to narrow results by date range, data source, compliance framework, or data type. +- **Drill down** — Click on chart elements or table rows to view detailed breakdowns of the underlying data. +- **Adjust time ranges** — Modify the reporting period to compare findings across different scan windows. + +:::note +Dashboards display data from the most recent completed scans. If you do not see expected results, verify that a [sensitive data scan](/docs/accessanalyzer/1_0/sensitivedatadiscovery/runningscan) has been run against the target data sources. +::: + +## Next Steps + +- [Save reports](/docs/accessanalyzer/1_0/dashboards/metabase/savedreports) for repeated access +- [Export report data](/docs/accessanalyzer/1_0/dashboards/metabase/exportingdata) for external use diff --git a/docs/accessanalyzer/1.0/dashboards/metabase/exportingdata.md b/docs/accessanalyzer/1.0/dashboards/metabase/exportingdata.md new file mode 100644 index 0000000000..9b8531c8e7 --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards/metabase/exportingdata.md @@ -0,0 +1,41 @@ +--- +title: "Exporting Report Data" +description: "Exporting report data for external use" +sidebar_position: 30 +--- + +# Exporting Report Data + +Access Analyzer allows you to export dashboard data from embedded Metabase reports for use in external tools, compliance documentation, or offline analysis. + +## Exporting from a Dashboard + +To export data from a dashboard or saved report: + +1. Open the desired dashboard or [saved report](/docs/accessanalyzer/1_0/dashboards/metabase/savedreports). +2. Apply any filters to scope the data to your requirements. +3. Click the **Export** button in the dashboard toolbar. +4. Select the export format: + - **CSV** — Comma-separated values for use in spreadsheets and data processing tools + - **JSON** — Structured data format for programmatic consumption + - **PDF** — Formatted report suitable for distribution and compliance documentation +5. Click **Download** to save the exported file. + +## Export Scope + +The exported data reflects the current dashboard view, including all applied filters. Only the data visible in the current report configuration is included in the export. + +| Export Format | Best For | +| --- | --- | +| CSV | Importing into Excel, Google Sheets, or data analysis tools | +| JSON | Integration with APIs, scripts, or automated reporting pipelines | +| PDF | Sharing with stakeholders, auditors, or compliance teams | + +:::warning +Exported reports may contain sensitive data findings. Handle exported files according to your organization's data handling and classification policies. +::: + +## Next Steps + +- [Configure saved reports](/docs/accessanalyzer/1_0/dashboards/metabase/savedreports) to streamline recurring exports +- [Review sensitive data scan results](/docs/accessanalyzer/1_0/sensitivedatadiscovery/reviewingresults/matchcounts) for detailed match-level data diff --git a/docs/accessanalyzer/1.0/dashboards/metabase/savedreports.md b/docs/accessanalyzer/1.0/dashboards/metabase/savedreports.md new file mode 100644 index 0000000000..8d565d14fe --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards/metabase/savedreports.md @@ -0,0 +1,38 @@ +--- +title: "Saved Reports" +description: "Creating and managing saved reports" +sidebar_position: 20 +--- + +# Saved Reports + +The saved reports feature allows you to preserve specific dashboard configurations, including applied filters and selected parameters, for quick access in future sessions. + +## Saving a Report + +1. Open a dashboard and apply the desired filters (date range, data source, compliance framework, or other parameters). +2. Click the **Save Report** button in the dashboard toolbar. +3. Enter a **Name** for the saved report. +4. Optionally add a **Description** to document the report's purpose. +5. Click **Save**. + +The saved report appears in your **Saved Reports** list for future access. + +## Managing Saved Reports + +To view and manage your saved reports: + +1. Navigate to **Dashboards** > **Saved Reports**. +2. The list displays all saved reports with their name, description, and creation date. +3. Click a saved report to load it with the preserved filter configuration. +4. To update a saved report, modify the filters and click **Save Report** again, then choose to overwrite the existing report. +5. To delete a saved report, select it and click **Delete**. + +:::note +Saved reports retain the filter configuration, not a static snapshot of the data. When you open a saved report, the dashboard applies the saved filters against the latest scan data, ensuring results are always current. +::: + +## Next Steps + +- [Export report data](/docs/accessanalyzer/1_0/dashboards/metabase/exportingdata) from a saved report configuration +- [Return to the dashboards overview](/docs/accessanalyzer/1_0/dashboards/overview) to explore other reporting options diff --git a/docs/accessanalyzer/1.0/dashboards/overview.md b/docs/accessanalyzer/1.0/dashboards/overview.md new file mode 100644 index 0000000000..d996ab6f5f --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards/overview.md @@ -0,0 +1,33 @@ +--- +title: "Dashboards and Reports" +description: "Overview of dashboards, metrics, and reporting capabilities" +sidebar_position: 10 +--- + +# Dashboards and Reports + +Netwrix Access Analyzer provides embedded analytics dashboards powered by Metabase. The **Dashboards** section gives you visual insight into your organization's data security posture, sensitive data findings, and access risk summaries. + +## Embedded Analytics + +Access Analyzer integrates Metabase as an embedded reporting engine with an airgap premium token. Authentication is handled automatically through JWT-based single sign-on from the Core API to Metabase, so users access dashboards directly from within the Access Analyzer interface without separate login credentials. + +## Available Dashboards + +Pre-built dashboards are visible in the **Dashboards** section of the application. The primary dashboard is the **Data Security Dashboard**, which provides: + +- **Sensitive data findings summary** — Aggregated match counts across all scanned sources +- **Risk summary** — High-level view of data exposure organized by severity and compliance framework +- **Trend analysis** — Changes in sensitive data findings over time + +## Reporting Capabilities + +| Feature | Description | +| --- | --- | +| [Accessing Reports](/docs/accessanalyzer/1_0/dashboards/metabase/accessingreports) | View and interact with embedded Metabase reports | +| [Saved Reports](/docs/accessanalyzer/1_0/dashboards/metabase/savedreports) | Save report configurations for repeated use | +| [Exporting Data](/docs/accessanalyzer/1_0/dashboards/metabase/exportingdata) | Export dashboard data for external analysis or compliance documentation | + +:::note +Dashboard content updates automatically as new scan results become available. Run a [sensitive data scan](/docs/accessanalyzer/1_0/sensitivedatadiscovery/runningscan) to populate dashboards with the latest findings. +::: diff --git a/docs/accessanalyzer/1.0/gettingstarted/_category_.json b/docs/accessanalyzer/1.0/gettingstarted/_category_.json new file mode 100644 index 0000000000..c8341a5bc3 --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Getting Started", + "position": 20, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/gettingstarted/dashboardwalkthrough.md b/docs/accessanalyzer/1.0/gettingstarted/dashboardwalkthrough.md new file mode 100644 index 0000000000..1416847ba0 --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/dashboardwalkthrough.md @@ -0,0 +1,44 @@ +--- +title: "Overview Dashboard Walkthrough" +description: "Navigating the main dashboard and key metrics" +sidebar_position: 30 +--- + +# Overview Dashboard Walkthrough + +After signing in, Access Analyzer displays the main interface with a sidebar navigation menu and a central content area. This page introduces the key areas of the application. + +## Sidebar Navigation + +The sidebar provides access to all major sections: + +| Section | Description | +| --- | --- | +| **Dashboards** | Pre-built Metabase dashboards for data security posture and identity analysis | +| **Reports** | Access, content, activity, and sensitive data reports | +| **Configuration** | Sources, scans, scan executions, and sensitive data settings | +| **Service Accounts** | Manage credentials used to connect to data sources | +| **Administration** | User management and system logs (administrator only) | +| **Settings** | Application-wide settings | + +## Dashboards + +The **Dashboards** section contains embedded Metabase dashboards that provide a visual summary of your environment: + +- **Data Security Dashboard** — Overview of sensitive data findings, file statistics, and framework coverage +- Additional dashboards become available as you add data sources and run scans + +Dashboards update automatically after each scan execution. + +## Configuration Section + +The **Configuration** section is where most of the day-to-day work happens: + +- **Sources** — Add and manage the data sources and identity providers Access Analyzer connects to +- **Scans** — Create, schedule, and manage access scans and sensitive data scans +- **Scan Executions** — View the history of scan runs, including status, duration, and progress +- **Sensitive Data** — Configure the detection frameworks and patterns used during sensitive data scans + +## Next Steps + +- [Your First Scan](/docs/accessanalyzer/1_0/gettingstarted/firstscan/overview) — Follow the step-by-step guide to add a source, configure a scan, and review results diff --git a/docs/accessanalyzer/1.0/gettingstarted/firstlogin.md b/docs/accessanalyzer/1.0/gettingstarted/firstlogin.md new file mode 100644 index 0000000000..defd35ef14 --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/firstlogin.md @@ -0,0 +1,52 @@ +--- +title: "First Login and Admin Setup" +description: "Initial administrator account creation and login" +sidebar_position: 20 +--- + +# First Login and Admin Setup + +After installing Access Analyzer, the first step is to access the web interface, create your administrator account, and sign in. + +## Access the Application + +Open a browser and navigate to: + +``` +https:// +``` + +Replace `` with the IP address or hostname of the VM where Access Analyzer is installed. + +:::note +Access Analyzer uses a self-signed TLS certificate by default. Your browser will display a security warning — accept the warning to proceed to the login page. To use a trusted certificate, see [SSL / TLS Configuration](/docs/accessanalyzer/1_0/install/ssl). +::: + +## Create the Administrator Account + +The first user to create an account is automatically assigned the **Administrator** role. + +1. On the login page, click **Create Account** +2. Enter the following: + - **Full Name** — Your display name + - **Email Address** — Used as your login username + - **Password** — Must meet complexity requirements + - **Confirm Password** — Re-enter the password +3. Click **Create Account** + +:::warning +The first account created receives full administrator privileges. Ensure this account is created by an authorized administrator. +::: + +## Sign In + +1. Enter the email address and password you used during account creation +2. Click **Sign In** + +You are now signed in with full administrator access. + +## Next Steps + +- [Overview Dashboard Walkthrough](/docs/accessanalyzer/1_0/gettingstarted/dashboardwalkthrough) — Explore the main interface +- [Your First Scan](/docs/accessanalyzer/1_0/gettingstarted/firstscan/overview) — Add a data source and run your first scan +- [Users and Roles](/docs/accessanalyzer/1_0/admin/users/overview) — Create additional user accounts diff --git a/docs/accessanalyzer/1.0/gettingstarted/firstscan/_category_.json b/docs/accessanalyzer/1.0/gettingstarted/firstscan/_category_.json new file mode 100644 index 0000000000..d8feb251f3 --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/firstscan/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Your First Scan", + "position": 30, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/gettingstarted/firstscan/addingsource.md b/docs/accessanalyzer/1.0/gettingstarted/firstscan/addingsource.md new file mode 100644 index 0000000000..b37b596118 --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/firstscan/addingsource.md @@ -0,0 +1,70 @@ +--- +title: "Adding a Data Source" +description: "Connect a data source using the Connect Source wizard" +sidebar_position: 20 +--- + +# Adding a Data Source + +Before scanning, you need to connect a data source to Access Analyzer. The **Connect Source** wizard guides you through a 3-step process: select the source type, configure the connection, and set up a scan. + +## Open the Connect Source Wizard + +1. Navigate to **Configuration** > **Sources** in the sidebar +2. Click **Connect Source** to open the wizard drawer + +## Step 1 — Select Source Type + +Choose the type of data source to connect: + +| Source Type | Category | Description | +| --- | --- | --- | +| **Active Directory** | IAM | Domain controllers, users, groups, and permissions | +| **Entra ID** | IAM | Azure AD tenant with users, groups, and roles | +| **File Server** | Data Source | Windows file shares (CIFS/SMB) | +| **SharePoint Online** | Data Source | SharePoint sites and document libraries | + +Select a source type card and click **Next**. + +## Step 2 — Configure the Source + +Configuration varies by source type. For this getting started guide, we'll walk through the **File Server** example — the most common first source. + +### File Server Configuration + +1. Enter a **Source Group Name** (for example, `Finance File Servers`) +2. Select or create a **Service Account**: + - Click **+ Create New Account** to add credentials inline + - Select **Username/Password** and enter the username and password for an account with read access to the target file servers + - Or select an existing service account from the dropdown +3. Optionally enter a **Domain** name (for example, `company.local`) + +### Add File Servers + +1. Click **+ Add** or the empty state area +2. Select **Add Manually** +3. Enter one or more server names or IP addresses, separated by commas or pressing **Enter** after each +4. Set the **Port** (default: `445`) +5. Click **Add file servers**, then click **Done** + +### Test Connection (Optional) + +Click **Test Connection** to verify connectivity to all servers. Each server shows its connection status (Connected, Failed, or Testing). Testing is non-blocking — you can proceed regardless of results. + +:::note +If a connection test fails, verify network connectivity on port 445 and that the service account has read access to the target shares. +::: + +Click **Next** to proceed to scan setup. + +### Other Source Types + +For detailed configuration instructions for each source type, see: + +- [Active Directory](/docs/accessanalyzer/1_0/connectors/iam/activedirectory/connectionsetup) — Domain controller configuration +- [Entra ID](/docs/accessanalyzer/1_0/connectors/iam/entraid/appregistration) — Azure AD app registration and tenant setup +- [SharePoint Online](/docs/accessanalyzer/1_0/connectors/source/sharepointonline/connectionconfig) — Site collection configuration + +## Next Step + +[Configuring a Scan](/docs/accessanalyzer/1_0/gettingstarted/firstscan/configuringscan) — Set up scanning options and schedule your first scan. diff --git a/docs/accessanalyzer/1.0/gettingstarted/firstscan/configuringscan.md b/docs/accessanalyzer/1.0/gettingstarted/firstscan/configuringscan.md new file mode 100644 index 0000000000..14df574f12 --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/firstscan/configuringscan.md @@ -0,0 +1,94 @@ +--- +title: "Configuring a Scan" +description: "Set up scanning options and schedule in the Connect Source wizard" +sidebar_position: 30 +--- + +# Configuring a Scan + +Step 3 of the Connect Source wizard configures what to scan and when. The available options depend on the source type selected in Step 1. + +## Available Scanning Options + +Select which scan types to enable for the source group. Available options vary by source type: + +### File Server Scan Types + +| Scan Type | Description | +| --- | --- | +| **Access** | Scan file server permissions and access controls | +| **Sensitive Data** | Scan file contents for sensitive data patterns (PII, credentials, PHI, financial data) | + +At least one scan type must be enabled to proceed. + +:::info +When the **Access** scan is enabled, a **Local Users and Groups** scan is also created automatically to collect local account data from each file server. This happens behind the scenes and does not require additional configuration. +::: + +### Entra ID Scan Types + +| Scan Type | Description | +| --- | --- | +| **Users, Groups and Roles** | Synchronize users, groups, and directory roles from the Azure AD tenant | + +This scan type is always enabled and cannot be disabled. Additional sync options (such as **Sync Sensitivity Labels**) may appear below the toggle. + +### Active Directory Scan Types + +| Scan Type | Description | +| --- | --- | +| **Active Directory Inventory** | Synchronize users, groups, OUs, and permissions from domain controllers | + +## Access Scan Options (File Server) + +When the **Access** scan type is enabled for a File Server source, additional configuration options appear: + +### Share Selection + +- **Include Shares** — Choose **All shares** (default) or **Custom selection** to specify specific share names +- **Exclude Shares** — Optionally list shares to skip (for example, `admin$, ipc$`) + +### Scan Depth + +- Maximum folder depth to scan (default: **50**) +- Controls how many levels of subdirectories the connector traverses + +### File-Level Permissions + +- Check **Include file-level permission data in scan results** to collect NTFS ACLs on individual files +- Disabled by default — increases scan duration on large file servers + +### Hidden Shares + +- Check **Automatically enumerate and scan hidden shares** to discover shares ending with `$` +- When enabled, an **Exclude Hidden Shares** field appears to specify hidden shares to skip (for example, `ADMIN$, C$, IPC$`) + +### Worker Threads + +- Number of concurrent workers for parallel directory enumeration (default: **3**) +- Higher values scan faster but increase load on the file server + +For detailed information about each option, see the [CIFS connector documentation](/docs/accessanalyzer/1_0/connectors/source/cifs/connectionconfig). + +## Scan Start Time + +Choose when to run the first scan: + +| Option | Description | +| --- | --- | +| **Run scan now** | Execute immediately after setup completes (default) | +| **Run scan at** | Schedule for a specific date and time — must be in the future | +| **Advanced scheduling** | Configure a recurring schedule using a cron expression | + +## Complete Setup + +Click **Complete Setup** to create the source group with all configured sources and scans. On success: + +1. The source group and all sources are created +2. Scans are created according to your configuration +3. The wizard closes and the sources list refreshes +4. Scans execute according to the selected schedule + +## Next Step + +[Running and Monitoring a Scan](/docs/accessanalyzer/1_0/gettingstarted/firstscan/runningscan) — Track scan progress and review results. diff --git a/docs/accessanalyzer/1.0/gettingstarted/firstscan/overview.md b/docs/accessanalyzer/1.0/gettingstarted/firstscan/overview.md new file mode 100644 index 0000000000..9d968a68bd --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/firstscan/overview.md @@ -0,0 +1,28 @@ +--- +title: "Your First Scan" +description: "Step-by-step guide to running your first scan" +sidebar_position: 10 +--- + +# Your First Scan + +This guide walks you through the complete workflow of adding a data source, creating a scan, running it, and reviewing the results. The example uses a CIFS/SMB file share, but the workflow is similar for all source types. + +## Workflow Summary + +| Step | Description | Page | +| --- | --- | --- | +| 1 | Create a service account with credentials for your data source | [Adding a Data Source](/docs/accessanalyzer/1_0/gettingstarted/firstscan/addingsource) | +| 2 | Add a data source and test the connection | [Adding a Data Source](/docs/accessanalyzer/1_0/gettingstarted/firstscan/addingsource) | +| 3 | Create a scan and select scan type | [Configuring a Scan](/docs/accessanalyzer/1_0/gettingstarted/firstscan/configuringscan) | +| 4 | Run the scan and monitor progress | [Running and Monitoring a Scan](/docs/accessanalyzer/1_0/gettingstarted/firstscan/runningscan) | +| 5 | Review findings in dashboards and scan results | [Viewing Results](/docs/accessanalyzer/1_0/gettingstarted/firstscan/viewingresults) | + +## Prerequisites + +Before starting, ensure you have: + +- Signed in as an administrator — see [First Login](/docs/accessanalyzer/1_0/gettingstarted/firstlogin) +- A data source available on the network (for example, a CIFS/SMB file share) +- Credentials with read access to the data source +- Network connectivity from the Access Analyzer VM to the data source (for example, port 445 for SMB) diff --git a/docs/accessanalyzer/1.0/gettingstarted/firstscan/runningscan.md b/docs/accessanalyzer/1.0/gettingstarted/firstscan/runningscan.md new file mode 100644 index 0000000000..9d9f001798 --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/firstscan/runningscan.md @@ -0,0 +1,56 @@ +--- +title: "Running and Monitoring a Scan" +description: "Execute a scan and monitor its progress" +sidebar_position: 40 +--- + +# Running and Monitoring a Scan + +Once a scan is created, you can run it immediately or let it execute on its configured schedule. + +## Running a Scan + +There are two ways to start a scan: + +- **From the scan creation wizard** — Select **Create & Run Immediately** in the final step +- **From the Scans list** — Navigate to **Configuration** > **Scans**, click the menu button on the scan row, and select **Run** + +## Monitoring Scan Progress + +Navigate to **Configuration** > **Scan Executions** to view all scan runs. + +Each execution displays: + +| Field | Description | +| --- | --- | +| **Scan Name** | The name of the scan | +| **Scan Type** | Access or Sensitive Data | +| **Source** | The data source being scanned | +| **Status** | Running, Completed, Failed, or Paused | +| **Start Time** | When the scan execution began | +| **Duration** | Elapsed time since the scan started | + +You can filter executions by scan type, source, status, date range, and duration. + +## Scan Execution Actions + +While a scan is running, the following actions are available from the execution row menu: + +| Action | Description | +| --- | --- | +| **Stop** | Cancel the running scan | +| **Pause** | Pause the scan (CIFS/SMB sources only) | +| **Resume** | Resume a paused scan (CIFS/SMB sources only) | + +## Scan Statuses + +| Status | Meaning | +| --- | --- | +| **Running** | Scan is actively processing | +| **Completed** | Scan finished successfully | +| **Failed** | Scan encountered an error — check the execution logs | +| **Paused** | Scan has been paused and can be resumed | + +## Next Step + +[Viewing Results](/docs/accessanalyzer/1_0/gettingstarted/firstscan/viewingresults) — Review the findings from your completed scan. diff --git a/docs/accessanalyzer/1.0/gettingstarted/firstscan/viewingresults.md b/docs/accessanalyzer/1.0/gettingstarted/firstscan/viewingresults.md new file mode 100644 index 0000000000..f41a7de471 --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/firstscan/viewingresults.md @@ -0,0 +1,49 @@ +--- +title: "Viewing Results" +description: "Review scan results and findings" +sidebar_position: 50 +--- + +# Viewing Results + +After a scan completes, results are available in the dashboards and reports sections. + +## Data Security Dashboard + +Navigate to **Dashboards** > **Data Security Dashboard** to view a summary of findings from your scans. The dashboard provides visualizations for: + +- Sensitive data findings by type and compliance framework +- File and data statistics +- Data exposure and risk indicators + +The dashboard updates automatically after each scan execution completes. + +## Scan Execution Details + +For per-scan results, navigate to **Configuration** > **Scan Executions**: + +1. Find the completed scan execution in the list +2. Click on the execution to view detailed results +3. Review the findings, including: + - Files and folders analyzed + - Permissions and access paths discovered + - Sensitive data matches (for sensitive data scans) + +## Reports + +Access Analyzer provides several report categories accessible from the sidebar: + +| Report Type | Description | +| --- | --- | +| **Access Reports** | Permission analysis and access path details | +| **Content Reports** | File and folder inventory statistics | +| **Sensitive Data Reports** | Sensitive data findings by category and compliance framework | + +## What's Next + +Now that you have completed your first scan and reviewed the results, consider these next steps: + +- **Add more data sources** — Connect additional file shares, SharePoint sites, or identity providers. See [Connectors](/docs/accessanalyzer/1_0/connectors/overview). +- **Configure sensitive data detection** — Customize detection patterns and taxonomy groups. See [Sensitive Data Discovery](/docs/accessanalyzer/1_0/sensitivedatadiscovery/overview). +- **Schedule recurring scans** — Set up automated scan schedules to maintain continuous visibility. See [Scans](/docs/accessanalyzer/1_0/admin/scans/overview). +- **Create additional users** — Add team members with appropriate roles. See [Users and Roles](/docs/accessanalyzer/1_0/admin/users/overview). diff --git a/docs/accessanalyzer/1.0/gettingstarted/overview.md b/docs/accessanalyzer/1.0/gettingstarted/overview.md new file mode 100644 index 0000000000..bb9c6c66f8 --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/overview.md @@ -0,0 +1,26 @@ +--- +title: "Getting Started" +description: "Get up and running with Access Analyzer" +sidebar_position: 10 +--- + +# Getting Started + +This section walks you through the initial setup steps after installing Access Analyzer, from your first login to running your first scan and reviewing results. + +## Getting Started Steps + +| Step | Description | Page | +| --- | --- | --- | +| 1 | Sign in and create your administrator account | [First Login and Admin Setup](/docs/accessanalyzer/1_0/gettingstarted/firstlogin) | +| 2 | Explore the main dashboard and navigation | [Overview Dashboard Walkthrough](/docs/accessanalyzer/1_0/gettingstarted/dashboardwalkthrough) | +| 3 | Add a data source, configure a scan, and view results | [Your First Scan](/docs/accessanalyzer/1_0/gettingstarted/firstscan/overview) | + +## Prerequisites + +Before starting this guide, ensure you have: + +- Completed the [installation](/docs/accessanalyzer/1_0/install/overview) of Access Analyzer +- Verified that all services are healthy — see [Post-Installation Validation](/docs/accessanalyzer/1_0/install/postinstall) +- Network connectivity from the Access Analyzer VM to the data sources you plan to scan +- Credentials (service account) for the data sources you want to connect diff --git a/docs/accessanalyzer/1.0/index.md b/docs/accessanalyzer/1.0/index.md new file mode 100644 index 0000000000..ee95583019 --- /dev/null +++ b/docs/accessanalyzer/1.0/index.md @@ -0,0 +1,30 @@ +--- +title: "Netwrix Access Analyzer Documentation" +description: "Netwrix Access Analyzer 1.0 product documentation - installation, administration, connectors, and sensitive data discovery" +sidebar_position: 1 +--- + +# Netwrix Access Analyzer Documentation + +Netwrix Access Analyzer is a cloud-native Data Security Posture Management (DSPM) platform that helps organizations discover, classify, and monitor sensitive data across enterprise systems and cloud storage. It provides comprehensive visibility into data access patterns, identifies compliance risks, and enables data governance at scale. + +## Key Capabilities + +- **Data Source Scanning** — Connect to CIFS/SMB file shares, SharePoint Online, and more to discover and analyze data +- **Sensitive Data Discovery** — Detect sensitive data using built-in and custom regex patterns with taxonomy-based classification +- **Identity and Access Management** — Sync users and groups from Active Directory and Entra ID to analyze permission paths +- **Activity Monitoring** — Track file access and user activity via Netwrix Activity Monitor integration +- **Dashboards and Reporting** — Visualize security posture with built-in dashboards and embedded Metabase reports + +## Documentation Sections + +- [Overview](overview/overview) — Architecture, components, and key concepts +- [Getting Started](gettingstarted/overview) — First login, dashboard walkthrough, and your first scan +- [Requirements](requirements/overview) — System, database, and connector prerequisites +- [Installation](install/overview) — Kubernetes deployment, infrastructure setup, and database initialization +- [Administration](admin/overview) — User management, sources, scans, and application settings +- [Connectors](connectors/overview) — IAM and source connector configuration +- [Sensitive Data Discovery](sensitivedatadiscovery/overview) — Patterns, taxonomy, classification, and scan results +- [Dashboards and Reports](dashboards/overview) — Built-in dashboards and Metabase reporting +- [Activity Monitoring](activitymonitoring/overview) — Syslog integration with Netwrix Activity Monitor +- [Monitoring and Troubleshooting](troubleshooting/overview) — Health checks, observability, and common issues diff --git a/docs/accessanalyzer/1.0/install/_category_.json b/docs/accessanalyzer/1.0/install/_category_.json new file mode 100644 index 0000000000..f5134e8f2b --- /dev/null +++ b/docs/accessanalyzer/1.0/install/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Installation", + "position": 40, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/install/dspmctl.md b/docs/accessanalyzer/1.0/install/dspmctl.md new file mode 100644 index 0000000000..7bdc4cc594 --- /dev/null +++ b/docs/accessanalyzer/1.0/install/dspmctl.md @@ -0,0 +1,141 @@ +--- +title: "DSPMctl CLI" +description: "Command-line reference for the DSPMctl application management tool" +sidebar_position: 45 +--- + +# DSPMctl CLI + +DSPMctl is a command-line tool installed by the Access Analyzer installer at `/usr/local/bin/dspmctl`. It provides convenient commands for managing ArgoCD-deployed applications without requiring direct `kubectl` or ArgoCD CLI interaction. + +## Commands + +### auto-status + +Display the current sync and auto-sync status of all applications: + +```bash +dspmctl auto-status +``` + +### enable-auto + +Enable auto-sync for a specific application. When auto-sync is enabled, ArgoCD automatically applies changes when the target revision is updated in the OCI registry: + +```bash +dspmctl enable-auto +``` + +**Example:** + +```bash +dspmctl enable-auto netwrix.core-api +``` + +### disable-auto + +Disable auto-sync for a specific application: + +```bash +dspmctl disable-auto +``` + +### set-revision + +Update the target revision (version) for an application or application set: + +```bash +dspmctl set-revision +``` + +**Example:** + +```bash +dspmctl set-revision netwrix 1.0.6 +``` + +### sync + +Manually trigger a sync for a specific application: + +```bash +dspmctl sync +``` + +**Example:** + +```bash +dspmctl sync netwrix.core-api +``` + +### set-helm-param + +Set one or more Helm parameter overrides for an application: + +```bash +dspmctl set-helm-param +dspmctl set-helm-param = [= ...] +``` + +**Examples:** + +```bash +# Set a single parameter +dspmctl set-helm-param netwrix.core-api image.tag v1.2.3 + +# Set multiple parameters +dspmctl set-helm-param netwrix.core-api image.tag=v1.2.3 replicaCount=2 +``` + +### version + +Display the DSPMctl version: + +```bash +dspmctl version +``` + +### help + +Display usage information: + +```bash +dspmctl --help +``` + +## Common Workflows + +### Upgrading to a New Version + +To update all applications to a new target revision: + +```bash +# Set the new version +dspmctl set-revision netwrix 1.0.7 + +# Verify applications are syncing +dspmctl auto-status + +# Force sync if needed +dspmctl sync netwrix.infra +dspmctl sync netwrix.core-api +``` + +See [Upgrading Access Analyzer](/docs/accessanalyzer/1_0/install/upgrade) for the full upgrade procedure. + +### Scaling an Application + +```bash +dspmctl set-helm-param netwrix.core-api replicaCount 3 +``` + +### Checking Deployment Health + +```bash +# Check auto-sync status +dspmctl auto-status + +# Also verify with kubectl +kubectl get apps -n argocd +kubectl get pods -n access-analyzer +``` diff --git a/docs/accessanalyzer/1.0/install/environmentvariables.md b/docs/accessanalyzer/1.0/install/environmentvariables.md new file mode 100644 index 0000000000..5b2cbb6d90 --- /dev/null +++ b/docs/accessanalyzer/1.0/install/environmentvariables.md @@ -0,0 +1,92 @@ +--- +title: "Environment Variables" +description: "CLI flags and environment variable reference for the Access Analyzer installer" +sidebar_position: 30 +--- + +# Environment Variables + +The Access Analyzer installer can be configured using command-line flags or environment variables. Environment variables are useful for scripted or automated installations. + +## CLI Flags + +``` +install.sh --license-key [options] + +Options: + --license-key Netwrix license key (required) + --target-revision Application version to deploy (default: 1.*) + --size Resource size multiplier, 1–10 (default: 1) + --accept-warnings Accept preflight warnings and continue + --dry-run Run preflight checks only, without installing + --help Display usage information +``` + +## Mandatory Variables + +| Variable | CLI Flag | Description | +| --- | --- | --- | +| `LICENSE_KEY` | `--license-key` | Netwrix license key for OCI registry authentication. Required for installation. | + +## Optional Configuration Variables + +| Variable | CLI Flag | Default | Description | +| --- | --- | --- | --- | +| `DSPM_TARGET_REVISION` | `--target-revision` | `1.*` | Target version for DSPM applications | +| `SIZE` | `--size` | `1` | Resource size multiplier (1–10). Scales memory thresholds. | +| `ACCEPT_WARNINGS` | `--accept-warnings` | `false` | Set to `true` to skip preflight warning prompts | + +## Proxy Variables + +| Variable | Description | Example | +| --- | --- | --- | +| `HTTP_PROXY` | HTTP proxy server URL | `http://proxy.example.com:8080` | +| `HTTPS_PROXY` | HTTPS proxy server URL | `http://proxy.example.com:8080` | +| `NO_PROXY` | Comma-separated list of hosts to bypass proxy | `localhost,127.0.0.1,10.0.0.0/8` | + +## Advanced Variables + +These variables are intended for specialized deployments and troubleshooting. They are not required for standard installations. + +| Variable | Default | Description | +| --- | --- | --- | +| `SKIP_AV_CHECK` | `false` | Skip antivirus detection during preflight | +| `FORCE_CA_MOUNT` | `false` | Force CA certificate bundle mounting to ArgoCD components | +| `USE_LOCAL_CHARTS` | `false` | Use local Helm charts instead of OCI registry | +| `USE_MIRRORED_IMAGES` | `true` | Use mirrored container images | +| `DISABLE_DEX` | `true` | Disable the Dex identity provider in ArgoCD | +| `DISABLE_NOTIFICATIONS` | `true` | Disable ArgoCD notifications | +| `DSPM_INSTALL_DEBUG` | Not set | Enable debug logging for the installer | + +## Examples + +**Basic installation:** + +```bash +export LICENSE_KEY='' +curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash - +``` + +**Installation with a specific version:** + +```bash +export LICENSE_KEY='' +curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- --target-revision "1.0.6" +``` + +**Scaled deployment (2x resources):** + +```bash +export LICENSE_KEY='' +curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- --size 2 +``` + +**Installation behind a proxy:** + +```bash +export LICENSE_KEY='' +export HTTP_PROXY="http://proxy.example.com:8080" +export HTTPS_PROXY="http://proxy.example.com:8080" +export NO_PROXY="localhost,127.0.0.1" +curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash - +``` diff --git a/docs/accessanalyzer/1.0/install/network.md b/docs/accessanalyzer/1.0/install/network.md new file mode 100644 index 0000000000..8e188d3da6 --- /dev/null +++ b/docs/accessanalyzer/1.0/install/network.md @@ -0,0 +1,96 @@ +--- +title: "Network Configuration" +description: "Network requirements, outbound endpoints, and firewall rules for Access Analyzer" +sidebar_position: 20 +--- + +# Network Configuration + +Access Analyzer requires outbound HTTPS connectivity during installation to download Kubernetes components, container images, and application packages. This page lists the required endpoints and provides firewall configuration examples. + +## Required Outbound Endpoints + +The following endpoints must be reachable over HTTPS (port 443) from the Access Analyzer VM: + +| Endpoint | Purpose | +| --- | --- | +| `get.k3s.io` | K3s installer download | +| `raw.githubusercontent.com` | ArgoCD manifests (bootstrap only) | +| `oci.pkg.keygen.sh` | Netwrix OCI registry — Helm charts and application images | +| `docker.io` / `docker.com` | Container base images (PostgreSQL, ClickHouse, Redis) | + +:::note +All application packages are distributed through the Netwrix OCI registry at `oci.pkg.keygen.sh`. Access is authenticated with your license key. No external Git repository access is required. +::: + +## Firewall Rules + +### Azure VMs (Network Security Group) + +```bash +az network nsg rule create \ + --resource-group \ + --nsg-name \ + --name AllowHTTPSOutbound \ + --protocol Tcp \ + --priority 1010 \ + --destination-port-range 443 \ + --direction Outbound \ + --access Allow +``` + +### AWS EC2 (Security Groups) + +```bash +aws ec2 authorize-security-group-egress \ + --group-id \ + --protocol tcp \ + --port 443 \ + --cidr 0.0.0.0/0 +``` + +### On-Premises / Bare Metal + +Using `ufw` (Ubuntu Firewall): + +```bash +sudo ufw allow out 443/tcp +``` + +Using `iptables`: + +```bash +sudo iptables -A OUTPUT -p tcp --dport 443 -j ACCEPT +``` + +## Proxy Configuration + +If your environment routes outbound traffic through a proxy server, set the following environment variables before running the installer: + +```bash +export HTTP_PROXY="http://:" +export HTTPS_PROXY="http://:" +export NO_PROXY="localhost,127.0.0.1,10.0.0.0/8" +``` + +See [Environment Variables](/docs/accessanalyzer/1_0/install/environmentvariables) for the full list of proxy-related variables. + +## Verifying Connectivity + +Test outbound access to the required endpoints before installation: + +```bash +# Test K3s installer access +curl -I https://get.k3s.io + +# Test Netwrix registry access +curl -I https://oci.pkg.keygen.sh:443 +``` + +## Common Network Issues + +| Issue | Symptom | Solution | +| --- | --- | --- | +| Applications not syncing | `connection refused` to Keygen | Verify outbound HTTPS (443) to `oci.pkg.keygen.sh` | +| K3s installation fails | Download errors | Check connectivity to `get.k3s.io` | +| Container image pull failures | `ImagePullBackOff` pod status | Verify access to `oci.pkg.keygen.sh` and license key validity | diff --git a/docs/accessanalyzer/1.0/install/overview.md b/docs/accessanalyzer/1.0/install/overview.md new file mode 100644 index 0000000000..af5712a7a3 --- /dev/null +++ b/docs/accessanalyzer/1.0/install/overview.md @@ -0,0 +1,49 @@ +--- +title: "Installation" +description: "Installation and deployment overview for Netwrix Access Analyzer" +sidebar_position: 1 +--- + +# Installation + +Netwrix Access Analyzer is deployed as a self-contained Kubernetes cluster on a single Linux virtual machine. The automated installer provisions all required infrastructure components — including K3s, ArgoCD, databases, and application services — with a single command. + +## Installation Paths + +Choose the installation path that best fits your needs: + +| Path | Description | Audience | +| --- | --- | --- | +| [Quick Install](/docs/accessanalyzer/1_0/install/quickinstall) | Single-page guide to get Access Analyzer running fast | Experienced Linux admins | +| [Step-by-Step Install](/docs/accessanalyzer/1_0/install/stepbystep) | Detailed walkthrough with explanations for each phase | First-time installers | + +## Before You Begin + +Review the following requirements before starting installation: + +- [Hardware and System Requirements](/docs/accessanalyzer/1_0/install/requirements) — CPU, memory, disk, OS, and virtualization +- [Network Configuration](/docs/accessanalyzer/1_0/install/network) — Outbound endpoints and firewall rules +- [Preflight Checks](/docs/accessanalyzer/1_0/install/preflight) — Automated system validation and dry-run mode + +## What the Installer Does + +The installer automates the entire deployment in approximately 15–30 minutes: + +1. **Validates prerequisites** — Runs preflight checks for hardware, OS, and network +2. **Deploys K3s** — Installs a lightweight Kubernetes distribution (v1.33.4) with secrets-at-rest encryption +3. **Installs ArgoCD** — Sets up GitOps-based application lifecycle management (v3.2.0) +4. **Deploys applications** — Pulls Helm charts from the Netwrix OCI registry and deploys all services +5. **Verifies health** — Monitors application health until all components are operational + +## After Installation + +- [Post-Installation Validation](/docs/accessanalyzer/1_0/install/postinstall) — Verify cluster health and access the ArgoCD UI +- [SSL / TLS Configuration](/docs/accessanalyzer/1_0/install/ssl) — Certificate auto-detection and custom CA bundles +- [DSPMctl CLI](/docs/accessanalyzer/1_0/install/dspmctl) — Manage applications with the built-in command-line tool + +## Additional Topics + +- [Environment Variables](/docs/accessanalyzer/1_0/install/environmentvariables) — CLI flags and environment variable reference +- [Upgrading Access Analyzer](/docs/accessanalyzer/1_0/install/upgrade) — Update to a new version +- [Uninstalling Access Analyzer](/docs/accessanalyzer/1_0/install/uninstall) — Remove the installation +- [Security Best Practices](/docs/accessanalyzer/1_0/install/security) — Harden your deployment diff --git a/docs/accessanalyzer/1.0/install/postinstall.md b/docs/accessanalyzer/1.0/install/postinstall.md new file mode 100644 index 0000000000..5f9372022a --- /dev/null +++ b/docs/accessanalyzer/1.0/install/postinstall.md @@ -0,0 +1,97 @@ +--- +title: "Post-Installation Validation" +description: "Verify cluster health and application status after installation" +sidebar_position: 40 +--- + +# Post-Installation Validation + +After the installer completes, validate that all Access Analyzer components are running correctly. + +## Cluster Health + +Verify that all Kubernetes pods are healthy: + +```bash +kubectl get pods -A -o wide +``` + +All pods should be in one of these states: + +| Status | Meaning | +| --- | --- | +| `Running` | Pod is active and healthy | +| `Completed` | One-time job completed successfully | + +If any pods show `CrashLoopBackOff`, `Error`, or `ImagePullBackOff`, see [Troubleshooting](/docs/accessanalyzer/1_0/troubleshooting/overview). + +## ArgoCD Application Status + +Check the sync and health status of all ArgoCD-managed applications: + +```bash +kubectl get apps -n argocd +``` + +Each application should show: + +| Field | Expected Value | +| --- | --- | +| **SYNC STATUS** | `Synced` | +| **HEALTH STATUS** | `Healthy` | + +## ArgoCD UI + +Access the ArgoCD web interface for a visual overview of all applications: + +1. Start port forwarding: + + ```bash + kubectl port-forward svc/argocd-server -n argocd 8090:443 + ``` + +2. Open `https://localhost:8090` in a browser + +3. Retrieve the admin password: + + ```bash + kubectl -n argocd get secret argocd-initial-admin-secret \ + -o jsonpath='{.data.password}' | base64 -d; echo + ``` + +4. Sign in with username `admin` and the retrieved password + +The ArgoCD dashboard displays each application's sync status, health, and resource tree. + +## Application Health Table + +The following components should be deployed and healthy after a successful installation: + +| Component | Namespace | Type | +| --- | --- | --- | +| **Core API** | `access-analyzer` | Rails application server | +| **Web Application** | `access-analyzer` | React frontend | +| **Connector API** | `access-analyzer` | Go connector execution service | +| **PostgreSQL** | `access-analyzer` | Primary relational database | +| **ClickHouse** | `access-analyzer` | Analytics and log storage | +| **Redis** | `access-analyzer` | Session cache and job queues | +| **Metabase** | `access-analyzer` | Embedded analytics dashboards | +| **Traefik** | `kube-system` | Ingress controller and routing | +| **OpenTelemetry Collector** | `access-analyzer` | Observability data pipeline | +| **Prometheus** | `access-analyzer` | Metrics collection | +| **ArgoCD** | `argocd` | GitOps application controller | + +## Resource Usage + +Monitor node-level resource consumption: + +```bash +kubectl top nodes +kubectl top pods -A --sort-by=memory +``` + +## Next Steps + +- [Create your first admin account](/docs/accessanalyzer/1_0/gettingstarted/firstlogin) and sign in +- [Configure a data source](/docs/accessanalyzer/1_0/gettingstarted/firstscan/overview) and run your first scan +- Review [DSPMctl CLI](/docs/accessanalyzer/1_0/install/dspmctl) for ongoing application management diff --git a/docs/accessanalyzer/1.0/install/preflight.md b/docs/accessanalyzer/1.0/install/preflight.md new file mode 100644 index 0000000000..6ac77af940 --- /dev/null +++ b/docs/accessanalyzer/1.0/install/preflight.md @@ -0,0 +1,111 @@ +--- +title: "Preflight Checks" +description: "System validation checks performed before installation" +sidebar_position: 25 +--- + +# Preflight Checks + +The Access Analyzer installer performs comprehensive system validation before any installation steps begin. Preflight checks verify hardware resources, kernel capabilities, and system access to prevent partial installation failures. + +## Dry-Run Mode + +Run preflight checks without installing anything using the `--dry-run` flag: + +```bash +export LICENSE_KEY='' +curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- --dry-run +``` + +Dry-run mode performs all validation checks and writes results to `/var/log/dspm-preflight.json`, then exits without modifying the system. + +## Phase 1: System Resource Validation + +| Check | Minimum | Recommended | Failure Behavior | +| --- | --- | --- | --- | +| **Total memory** | 8 GB | 16 GB | FAIL — installation blocked | +| **Available memory** | 4 GB (during install) | — | FAIL — installation blocked | +| **CPU cores** | 2 vCPUs | 4 vCPUs | FAIL — installation blocked | +| **Disk space (`/`, `/var`, `/var/lib`)** | 20 GB free | 50 GB free | FAIL — installation blocked | +| **Disk space (`/var/log`)** | 5 GB free | — | FAIL — installation blocked | +| **Disk space (`/etc`)** | 1 GB free | — | FAIL — installation blocked | +| **Write access** | `/var`, `/tmp`, `/etc` | — | FAIL — installation blocked | +| **Swap** | None required | 2–4 GB if RAM < 16 GB | WARN — continues with warning | +| **Dynamic memory** | N/A | Static allocation | WARN — continues with warning | + +## Phase 2: Kernel and System Access + +| Check | Requirement | Failure Behavior | +| --- | --- | --- | +| **System directories** | Write access to `/var` and `/etc` | FAIL — installation blocked | +| **Kernel modules** | `/proc/modules` readable | FAIL — installation blocked | +| **Control groups** | cgroups v1 or v2 with memory and CPU controllers | FAIL — installation blocked | +| **Overlay filesystem** | `overlay` kernel module loaded or available | FAIL — installation blocked | +| **Linux namespaces** | NET, PID, IPC, UTS, MNT, USER | FAIL — installation blocked | + +## Antivirus Detection + +The installer scans for active antivirus agents that may interfere with Kubernetes container operations: + +- Microsoft Defender for Endpoint (mdatp) +- CrowdStrike Falcon +- ClamAV +- Sophos +- Carbon Black +- Trend Micro + +If an antivirus agent is detected, the installer issues a warning. To skip this check, set the `SKIP_AV_CHECK` environment variable: + +```bash +export SKIP_AV_CHECK=true +``` + +## Preflight Result Log + +All preflight results are written to `/var/log/dspm-preflight.json` in structured JSON format: + +```json +{ + "timestamp": "2026-01-15T10:30:00Z", + "overall_status": "PASS", + "thresholds": { + "min_ram_gb": 8, + "min_cpu_cores": 2, + "min_disk_gb": 20 + }, + "checks": [ + { + "status": "PASS", + "component": "Memory", + "message": "Total memory sufficient for DSPM installation", + "current_value": "15.56 GB", + "threshold": "8 GB minimum" + } + ] +} +``` + +## Handling Warnings + +When preflight checks produce warnings (but no failures), the installer prompts for confirmation before proceeding. To automatically accept warnings — for example, in automated or scripted deployments — use one of the following: + +```bash +# CLI flag +curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- --accept-warnings + +# Environment variable +export ACCEPT_WARNINGS=true +``` + +## Exit Codes + +The installer uses specific exit codes to indicate failure categories: + +| Exit Code | Meaning | +| --- | --- | +| `0` | Success | +| `10` | License validation error | +| `50` | K3s installation error | +| `60` | ArgoCD installation error | +| `70` | Application deployment timeout | +| `80` | Preflight check failure | diff --git a/docs/accessanalyzer/1.0/install/quickinstall.md b/docs/accessanalyzer/1.0/install/quickinstall.md new file mode 100644 index 0000000000..f3e9e35808 --- /dev/null +++ b/docs/accessanalyzer/1.0/install/quickinstall.md @@ -0,0 +1,128 @@ +--- +title: "Quick Install" +description: "Get Access Analyzer up and running in minutes with this streamlined installation guide" +sidebar_position: 5 +--- + +# Quick Install + +This guide walks you through installing Netwrix Access Analyzer on a fresh Linux VM. For detailed explanations of each step, see the [Step-by-Step Installation](/docs/accessanalyzer/1_0/install/stepbystep) guide. + +## Prerequisites Checklist + +Before running the installer, confirm the following: + +| Requirement | Minimum | Recommended | +| --- | --- | --- | +| **Operating System** | Ubuntu 24.04 LTS (x86_64) | — | +| **Memory** | 8 GB RAM | 16 GB RAM | +| **CPU** | 2 vCPUs | 4 vCPUs | +| **Disk Space** | 20 GB free | 50 GB free | +| **Network** | Outbound HTTPS (port 443) | — | +| **License** | Valid Netwrix license key | — | + +:::note +If running on a hypervisor, configure **static memory allocation** (not dynamic/ballooned memory). See [Hardware and System Requirements](/docs/accessanalyzer/1_0/install/requirements) for hypervisor-specific instructions. +::: + +## Step 1: Prepare the System + +Update the operating system and verify internet connectivity: + +```bash +sudo apt update && sudo apt upgrade -y + +# Verify outbound access to the Netwrix registry +curl -I https://oci.pkg.keygen.sh:443 +``` + +## Step 2: Set Your License Key + +```bash +export LICENSE_KEY='' +``` + +:::warning +Your license key grants access to the Netwrix package registry. Keep it confidential and clear your shell history after installation. See [Security Best Practices](/docs/accessanalyzer/1_0/install/security). +::: + +## Step 3: Run the Installer + +Download and execute the installer in a single command: + +```bash +curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash - +``` + +The installer performs the following automatically: + +1. Preflight system validation (memory, CPU, disk, kernel) +2. K3s Kubernetes deployment (v1.33.4) +3. ArgoCD installation (v3.2.0) +4. Application deployment from the Netwrix OCI registry +5. Health verification of all components + +:::note +Installation typically takes 15–30 minutes depending on network speed and system resources. The installer displays progress in real time. +::: + +## Step 4: Verify the Installation + +After the installer completes, confirm all pods are running: + +```bash +kubectl get pods -A +``` + +All pods should show a `Running` or `Completed` status. Check ArgoCD application sync status: + +```bash +kubectl get apps -n argocd +``` + +## Step 5: Access the Application + +Open a browser and navigate to: + +``` +https:// +``` + +:::note +Access Analyzer uses a self-signed TLS certificate by default. Accept the browser security warning to proceed. +::: + +## Step 6: Create Your Admin Account + +1. On the login page, click **Create Account** +2. Enter your name, email address, and password +3. Click **Create Account** to finalize + +The first account created automatically receives the **Administrator** role. + +## Step 7: Sign In + +1. Enter your email address and password +2. Click **Sign In** + +You are now signed in to Netwrix Access Analyzer. See [Getting Started](/docs/accessanalyzer/1_0/gettingstarted/overview) for next steps, including configuring your first data source and running a scan. + +## Optional: Validate with Dry Run + +To validate system readiness without installing, use dry-run mode: + +```bash +curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- --dry-run +``` + +This runs all [preflight checks](/docs/accessanalyzer/1_0/install/preflight) and writes results to `/var/log/dspm-preflight.json` without modifying the system. + +## Troubleshooting + +If the installation fails, check the installer log: + +```bash +cat /var/log/dspm-installer.log +``` + +For common issues and resolutions, see [Troubleshooting](/docs/accessanalyzer/1_0/troubleshooting/overview). diff --git a/docs/accessanalyzer/1.0/install/requirements.md b/docs/accessanalyzer/1.0/install/requirements.md new file mode 100644 index 0000000000..885dc0fdaf --- /dev/null +++ b/docs/accessanalyzer/1.0/install/requirements.md @@ -0,0 +1,104 @@ +--- +title: "Hardware and System Requirements" +description: "System requirements for deploying Access Analyzer including hardware, OS, and virtualization" +sidebar_position: 10 +--- + +# Hardware and System Requirements + +Access Analyzer is deployed on a single Linux virtual machine. The installer runs preflight checks to validate that your system meets these requirements before installation begins. + +## Deployment Sizing + +| Size | CPU | Memory | Disk | Use Case | +| --- | --- | --- | --- | --- | +| **Small** | 2 vCPUs (4 recommended) | 8 GB (16 GB recommended) | 20 GB free (50 GB recommended) | Evaluation and small environments | +| **Medium** | 8 vCPUs | 32 GB | 100 GB SSD | Mid-size environments | +| **Large** | 16 vCPUs | 64 GB | 500 GB SSD | Large enterprise environments | + +:::note +The `--size` flag scales memory requirements by the specified multiplier. For example, `--size 2` doubles the minimum and recommended memory thresholds. See [Environment Variables](/docs/accessanalyzer/1_0/install/environmentvariables) for details. +::: + +## Disk Space Requirements + +The installer validates free space on the following paths: + +| Path | Minimum Free Space | Purpose | +| --- | --- | --- | +| `/` | 20 GB | Root filesystem | +| `/var` | 20 GB | K3s data, containers, logs | +| `/var/lib` | 20 GB | K3s data directory | +| `/var/log` | 5 GB | System and application logs | +| `/etc` | 1 GB | Configuration files | + +Write access is also verified for `/var`, `/tmp`, and `/etc`. + +## Operating System + +| Requirement | Value | +| --- | --- | +| **Distribution** | Ubuntu 24.04 LTS | +| **Architecture** | x86_64 (amd64) | +| **Kernel** | 5.15 or later | + +## Kernel and Container Runtime Requirements + +The installer validates the following kernel features required for Kubernetes container operation: + +| Feature | Description | +| --- | --- | +| **Linux Namespaces** | NET, PID, IPC, UTS, MNT, USER — required for container isolation | +| **Control Groups (cgroups)** | v1 or v2 with memory and CPU controllers | +| **Overlay Filesystem** | Kernel module for container image layers | +| **iptables** | Required for Kubernetes networking | + +## Virtualization and Hypervisor Configuration + +When deploying on a virtual machine, configure **static memory allocation** to ensure consistent performance. Dynamic or ballooned memory can cause the installer to underestimate available resources and lead to out-of-memory conditions during operation. + +### VMware vSphere / ESXi + +Disable memory ballooning in vSphere client under **VM Settings** > **VM Options** > **Advanced** > **Edit Configuration**: + +``` +sched.mem.pshare.enable = "FALSE" +mem.balloon.enable = "FALSE" +``` + +### Microsoft Hyper-V + +Configure static memory instead of dynamic memory: + +```powershell +Set-VMMemory -VMName "" -DynamicMemoryEnabled $false -StartupBytes 16GB +``` + +### KVM / QEMU + +Use hugepages for better memory performance. Add the following to your VM XML configuration: + +```xml + + + +``` + +## Swap Configuration + +| System Memory | Swap Recommendation | +| --- | --- | +| 16 GB or more | Optional | +| Less than 16 GB | 2–4 GB recommended | + +If no swap is configured on a system with less than 16 GB of RAM, the installer issues a warning. To create a swap file: + +```bash +sudo fallocate -l 4G /swapfile +sudo chmod 600 /swapfile +sudo mkswap /swapfile +sudo swapon /swapfile + +# Make permanent +echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab +``` diff --git a/docs/accessanalyzer/1.0/install/security.md b/docs/accessanalyzer/1.0/install/security.md new file mode 100644 index 0000000000..31ce8a735d --- /dev/null +++ b/docs/accessanalyzer/1.0/install/security.md @@ -0,0 +1,65 @@ +--- +title: "Security Best Practices" +description: "Security hardening recommendations for Access Analyzer deployments" +sidebar_position: 90 +--- + +# Security Best Practices + +Follow these recommendations to harden your Access Analyzer deployment. + +## License Key Protection + +Your Netwrix license key provides access to the OCI package registry. Treat it as a credential: + +- Do not commit license keys to version control +- Do not store license keys in plaintext configuration files +- Clear shell history after setting the `LICENSE_KEY` environment variable: + + ```bash + history -c + ``` + +## Network Security + +- Restrict access to the K3s API server (port 6443) to trusted networks only +- Limit inbound access to the Access Analyzer web interface to authorized IP ranges +- Use firewall rules to allow only the minimum required outbound endpoints — see [Network Configuration](/docs/accessanalyzer/1_0/install/network) + +## TLS / SSL + +- Replace the default self-signed certificate with a certificate issued by a trusted CA for production use +- Ensure outbound TLS verification is enabled by mounting your organization's CA bundle — see [SSL / TLS Configuration](/docs/accessanalyzer/1_0/install/ssl) + +## RBAC and Access Control + +- Limit the number of administrator accounts +- Use the **Viewer** role for users who only need read access +- Review user accounts periodically and remove unused accounts + +## Token and Credential Rotation + +- Rotate the ArgoCD admin password after initial setup: + + ```bash + kubectl -n argocd patch secret argocd-initial-admin-secret \ + -p '{"data": {"password": "'$(echo -n '' | base64)'"}}' + ``` + +- Rotate service account credentials on a regular schedule + +## Audit Logging + +- Access Analyzer maintains an audit log of user actions — review it regularly in **Settings** > **Audit Logs** +- Monitor the installer log at `/var/log/dspm-installer.log` for installation-related events +- Monitor ArgoCD logs for application sync events: + + ```bash + kubectl logs -n argocd deployment/argocd-server + ``` + +## Kubernetes Security + +- Secrets at rest are encrypted by default (K3s `--secrets-encryption` flag) +- Kubeconfig file permissions are set to `644` — restrict further if the VM is shared +- Regularly apply OS security patches to the host VM diff --git a/docs/accessanalyzer/1.0/install/ssl.md b/docs/accessanalyzer/1.0/install/ssl.md new file mode 100644 index 0000000000..cebd210517 --- /dev/null +++ b/docs/accessanalyzer/1.0/install/ssl.md @@ -0,0 +1,56 @@ +--- +title: "SSL / TLS Configuration" +description: "Certificate auto-detection and custom CA bundle configuration for Access Analyzer" +sidebar_position: 60 +--- + +# SSL / TLS Configuration + +Access Analyzer uses HTTPS for all client-facing traffic, served through Traefik as the ingress controller. By default, a self-signed TLS certificate is generated during installation. This page covers certificate handling and custom CA bundle configuration. + +## Default Behavior + +After installation, Access Analyzer is accessible at `https://`. The default self-signed certificate causes browsers to display a security warning on first access. + +## Certificate Auto-Detection + +During installation, the installer scans for existing CA certificate bundles on the system. If a bundle is found, it is automatically mounted into ArgoCD components to enable TLS verification for outbound connections to the OCI registry and other external services. + +The installer searches the following paths: + +| Path | Description | +| --- | --- | +| `/etc/ssl/certs/ca-certificates.crt` | Debian/Ubuntu CA bundle | +| `/etc/pki/tls/certs/ca-bundle.crt` | RHEL/CentOS CA bundle | +| `/etc/ssl/ca-bundle.pem` | SUSE CA bundle | +| `/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem` | RHEL trust store | +| `/etc/ssl/cert.pem` | Alpine/macOS CA bundle | +| `/usr/local/share/ca-certificates/` | Custom CA directory | + +## Forcing CA Bundle Mounting + +If the installer does not detect your CA bundle automatically, or if you are using a custom internal CA, force CA bundle mounting with the `FORCE_CA_MOUNT` environment variable: + +```bash +export FORCE_CA_MOUNT=true +export LICENSE_KEY='' +curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash - +``` + +## Adding Custom CA Certificates + +To add a custom CA certificate to the system trust store before installation: + +```bash +# Copy your CA certificate to the system trust directory +sudo cp your-ca-cert.crt /usr/local/share/ca-certificates/ + +# Update the system CA bundle +sudo update-ca-certificates +``` + +Run the installer after updating the trust store. The installer will automatically detect and mount the updated bundle. + +## TLS for Internal Services + +All internal service-to-service communication within the Kubernetes cluster uses the cluster's internal networking. Traefik handles TLS termination at the ingress layer and routes traffic to backend services. diff --git a/docs/accessanalyzer/1.0/install/stepbystep.md b/docs/accessanalyzer/1.0/install/stepbystep.md new file mode 100644 index 0000000000..bd418170a7 --- /dev/null +++ b/docs/accessanalyzer/1.0/install/stepbystep.md @@ -0,0 +1,150 @@ +--- +title: "Step-by-Step Installation" +description: "Detailed walkthrough of the Access Analyzer installation process" +sidebar_position: 35 +--- + +# Step-by-Step Installation + +This guide provides a detailed walkthrough of the Netwrix Access Analyzer installation process with explanations for each phase. For a condensed version, see the [Quick Install](/docs/accessanalyzer/1_0/install/quickinstall) guide. + +## Pre-Installation Checklist + +Complete the following before starting the installer: + +| Step | Action | Reference | +| --- | --- | --- | +| 1 | Provision a Linux VM meeting hardware requirements | [Hardware and System Requirements](/docs/accessanalyzer/1_0/install/requirements) | +| 2 | Configure static memory allocation on the hypervisor | [Virtualization Configuration](/docs/accessanalyzer/1_0/install/requirements#virtualization-and-hypervisor-configuration) | +| 3 | Verify outbound HTTPS connectivity to required endpoints | [Network Configuration](/docs/accessanalyzer/1_0/install/network) | +| 4 | Obtain your Netwrix license key | Contact Netwrix Sales or Support | +| 5 | Update the operating system | See step 1 below | + +## Step 1: Update the Operating System + +Ensure all system packages are current: + +```bash +sudo apt update && sudo apt upgrade -y +``` + +Reboot if kernel updates were applied: + +```bash +sudo reboot +``` + +## Step 2: Validate System Readiness (Optional) + +Run the installer in dry-run mode to verify that the system meets all requirements without making changes: + +```bash +export LICENSE_KEY='' +curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- --dry-run +``` + +Review the results in `/var/log/dspm-preflight.json`. Address any `FAIL` items before proceeding. See [Preflight Checks](/docs/accessanalyzer/1_0/install/preflight) for details on each check. + +## Step 3: Set the License Key + +Export your Netwrix license key as an environment variable: + +```bash +export LICENSE_KEY='' +``` + +:::warning +Do not store the license key in scripts or configuration files that are committed to version control. Clear your shell history after installation — see [Security Best Practices](/docs/accessanalyzer/1_0/install/security). +::: + +## Step 4: Run the Installer + +Download and execute the installer: + +```bash +curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash - +``` + +The installer executes the following phases automatically: + +### Phase 1 — Preflight Checks + +The installer validates system resources (memory, CPU, disk), kernel features (cgroups, overlay FS, namespaces), and system access. If any critical check fails, the installer exits with code `80`. If warnings are present, you are prompted to continue or abort. + +### Phase 2 — K3s Installation + +K3s (v1.33.4+k3s1) is deployed as a lightweight Kubernetes distribution. The installer configures: + +- Kubeconfig permissions (`644`) +- Secrets-at-rest encryption +- K3s service name `dspm` + +### Phase 3 — ArgoCD Installation + +ArgoCD (v3.2.0) is deployed using Kustomize-based manifests with dynamic patches. ArgoCD provides GitOps-based application lifecycle management for all Access Analyzer components. + +### Phase 4 — DSPMctl Wrapper + +The `dspmctl` command-line tool is installed to `/usr/local/bin/dspmctl`. This tool provides convenient commands for managing ArgoCD applications. See [DSPMctl CLI](/docs/accessanalyzer/1_0/install/dspmctl). + +### Phase 5 — Application Deployment + +Applications are deployed from the Netwrix OCI registry (`oci://oci.pkg.keygen.sh/netwrix/dspm-apps-helm`). ArgoCD pulls Helm charts and deploys all services into the `access-analyzer` namespace. + +### Phase 6 — Health Verification + +The installer monitors application health with a 30-minute timeout, checking every 2 seconds. Once all applications report healthy status, the installer prints a success summary. + +## Step 5: Verify the Installation + +After the installer completes successfully, verify the cluster state: + +```bash +# Check all pods across all namespaces +kubectl get pods -A + +# Check ArgoCD application sync status +kubectl get apps -n argocd + +# Check node resource usage +kubectl top nodes +``` + +All pods should be in `Running` or `Completed` status. All ArgoCD applications should show `Synced` and `Healthy`. + +## Step 6: Access the Application + +Open a browser and navigate to: + +``` +https:// +``` + +:::note +Access Analyzer uses a self-signed TLS certificate by default. Your browser will display a security warning — accept it to proceed. See [SSL / TLS Configuration](/docs/accessanalyzer/1_0/install/ssl) for custom certificate setup. +::: + +## Step 7: Create the First Admin Account + +1. On the login page, click **Create Account** +2. Enter your full name, email address, and a password +3. Click **Create Account** + +The first account created is automatically assigned the **Administrator** role with full access to all features. + +## Step 8: Sign In + +1. Enter your email address and password +2. Click **Sign In** + +You are now ready to begin configuring Access Analyzer. See [Getting Started](/docs/accessanalyzer/1_0/gettingstarted/overview) for your next steps. + +## Installation Log + +The installer writes a detailed log to `/var/log/dspm-installer.log`. If the installation fails, review this file for diagnostic information: + +```bash +cat /var/log/dspm-installer.log +``` + +For additional troubleshooting guidance, see [Troubleshooting](/docs/accessanalyzer/1_0/troubleshooting/overview). diff --git a/docs/accessanalyzer/1.0/install/uninstall.md b/docs/accessanalyzer/1.0/install/uninstall.md new file mode 100644 index 0000000000..87d09af82f --- /dev/null +++ b/docs/accessanalyzer/1.0/install/uninstall.md @@ -0,0 +1,52 @@ +--- +title: "Uninstalling Access Analyzer" +description: "Remove Access Analyzer and all associated components" +sidebar_position: 80 +--- + +# Uninstalling Access Analyzer + +To completely remove Access Analyzer from the system, run the K3s uninstall script provided by the installer. + +:::warning +Uninstalling removes all Kubernetes resources, databases, and application data. This action is irreversible. Back up any data you need before proceeding. +::: + +## Uninstall Procedure + +### Step 1: Run the Uninstall Script + +```bash +sudo /usr/local/bin/k3s-dspm-uninstall.sh +``` + +This script: + +- Stops and removes the K3s service +- Deletes all Kubernetes resources (pods, services, volumes) +- Removes K3s binaries and configuration +- Cleans up container images and data + +### Step 2: Remove Remaining Configuration + +Remove the kubeconfig and DSPMctl configuration: + +```bash +rm -rf ~/.kube/config +sudo rm -rf /opt/dspm +sudo rm -f /usr/local/bin/dspmctl +``` + +### Step 3: Verify Removal + +Confirm that K3s is no longer running: + +```bash +systemctl status k3s-dspm +``` + +The service should not be found or should show as inactive. + +## Reinstallation + +After uninstalling, you can reinstall Access Analyzer by running the installer again. See [Quick Install](/docs/accessanalyzer/1_0/install/quickinstall) or [Step-by-Step Installation](/docs/accessanalyzer/1_0/install/stepbystep). diff --git a/docs/accessanalyzer/1.0/install/upgrade.md b/docs/accessanalyzer/1.0/install/upgrade.md new file mode 100644 index 0000000000..868b81dc33 --- /dev/null +++ b/docs/accessanalyzer/1.0/install/upgrade.md @@ -0,0 +1,77 @@ +--- +title: "Upgrading Access Analyzer" +description: "Update Access Analyzer to a new version using DSPMctl" +sidebar_position: 70 +--- + +# Upgrading Access Analyzer + +Access Analyzer uses ArgoCD for GitOps-based application management. Upgrades are performed by updating the target revision, which triggers ArgoCD to pull and deploy the new version from the Netwrix OCI registry. + +## Upgrade Procedure + +### Step 1: Check Current Version + +```bash +dspmctl auto-status +``` + +Note the current target revision displayed for each application. + +### Step 2: Set the New Target Revision + +Update the target revision to the desired version: + +```bash +dspmctl set-revision netwrix +``` + +**Example:** + +```bash +dspmctl set-revision netwrix 1.0.7 +``` + +### Step 3: Monitor the Upgrade + +If auto-sync is enabled, ArgoCD automatically detects the revision change and begins deploying the new version. Monitor the status: + +```bash +# Watch ArgoCD application sync status +kubectl get apps -n argocd -w + +# Check DSPMctl status +dspmctl auto-status +``` + +If auto-sync is not enabled, manually trigger the sync: + +```bash +dspmctl sync netwrix.infra +dspmctl sync netwrix.core-api +``` + +### Step 4: Verify the Upgrade + +Confirm all applications are synced and healthy: + +```bash +kubectl get apps -n argocd +kubectl get pods -n access-analyzer +``` + +All applications should show `Synced` and `Healthy` status. All pods should be `Running` or `Completed`. + +## Rollback + +To revert to a previous version, set the target revision back: + +```bash +dspmctl set-revision netwrix +``` + +ArgoCD will redeploy the previous version. + +:::warning +Test upgrades in a non-production environment before applying to production systems. +::: diff --git a/docs/accessanalyzer/1.0/overview/_category_.json b/docs/accessanalyzer/1.0/overview/_category_.json new file mode 100644 index 0000000000..5015c8e965 --- /dev/null +++ b/docs/accessanalyzer/1.0/overview/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Overview", + "position": 10, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/overview/architecture.md b/docs/accessanalyzer/1.0/overview/architecture.md new file mode 100644 index 0000000000..56014309b5 --- /dev/null +++ b/docs/accessanalyzer/1.0/overview/architecture.md @@ -0,0 +1,69 @@ +--- +title: "Architecture Overview" +description: "Core components and how they work together" +sidebar_position: 20 +--- + +# Architecture Overview + +Access Analyzer runs as a set of containerized services on a single-node Kubernetes cluster (K3s), managed by ArgoCD for automated deployment and updates. + +## Component Architecture + +| Component | Technology | Purpose | +| --- | --- | --- | +| **Core API** | Ruby on Rails 8 | Business logic, REST API, session management | +| **Web Application** | React 18, TypeScript | User interface and dashboards | +| **Connector API** | Go | Manages connector execution as Kubernetes Jobs | +| **PostgreSQL** | v14.18 | Primary relational database for configuration and scan metadata | +| **ClickHouse** | v25.8.13 | Analytics database for scan results, logs, and traces | +| **Redis** | v8.4.0 | Session storage, job queues, and caching | +| **Metabase** | Embedded (airgap) | Dashboard and reporting engine | +| **Traefik** | Ingress controller | TLS termination and request routing | +| **ArgoCD** | v3.2.0 | GitOps-based application lifecycle management | +| **K3s** | v1.33.4 | Lightweight Kubernetes distribution | +| **OpenTelemetry** | Collector | Observability data pipeline (traces and logs) | +| **Prometheus** | v3.8.0 | Metrics collection and alerting | + +## Communication Flow + +Access Analyzer operates in three phases: + +### Phase 1 — Installation + +The installer deploys K3s and ArgoCD on the target VM. ArgoCD connects to the Netwrix OCI registry to pull application Helm charts. + +### Phase 2 — Application Sync + +ArgoCD deploys applications in ordered sync waves: + +| Wave | Components | +| --- | --- | +| **Wave -5** | Secrets initialization (auto-generated database passwords, API keys) | +| **Wave 1** | Infrastructure: PostgreSQL, ClickHouse, Redis, OpenTelemetry, Prometheus, Traefik | +| **Wave 2** | Core services: Core API, Web Application, Connector API, Metabase | +| **Wave 3** | Functions and database seeds | + +### Phase 3 — Ongoing Operations + +- **Traefik** routes incoming requests: `/api/` → Core API, `/metabase` → Metabase, `/` → Web Application +- **Core API** processes user requests and schedules scan jobs via Sidekiq (Redis-backed job queues) +- **Connector API** executes connectors as Kubernetes Jobs to scan data sources +- **Metabase** provides embedded dashboards with JWT-based single sign-on from Core API +- **ArgoCD** continuously monitors the OCI registry for updates and applies changes automatically + +## Namespace Layout + +| Namespace | Contents | +| --- | --- | +| `access-analyzer` | All application workloads (Core API, databases, connectors, Metabase, observability) | +| `argocd` | ArgoCD server, application controller, and repo server | +| `kube-system` | Traefik ingress controller, K3s system components | + +## Data Stores + +| Database | Data Stored | +| --- | --- | +| **PostgreSQL** | Users, sources, scans, service accounts, connector state, configuration | +| **ClickHouse** | Scan results, analytics, OpenTelemetry traces and logs | +| **Redis** | User sessions, Sidekiq job queues, application cache | diff --git a/docs/accessanalyzer/1.0/overview/keyconcepts.md b/docs/accessanalyzer/1.0/overview/keyconcepts.md new file mode 100644 index 0000000000..409c8cd341 --- /dev/null +++ b/docs/accessanalyzer/1.0/overview/keyconcepts.md @@ -0,0 +1,87 @@ +--- +title: "Key Concepts" +description: "Sources, scans, patterns, identities, and entitlements" +sidebar_position: 30 +--- + +# Key Concepts + +This page defines the core terminology used throughout Access Analyzer. + +## Sources + +A **source** is a data repository or identity provider that Access Analyzer connects to for scanning. Sources are organized into two categories: + +- **Data sources** — File shares (CIFS/SMB), SharePoint Online sites, and other storage locations containing files and data +- **IAM sources** — Identity providers such as Active Directory, Entra ID, and local groups that contain users, groups, and permissions + +Each source is associated with a [service account](#service-accounts) that provides the credentials needed for Access Analyzer to connect. + +## Source Groups + +A **source group** is a named collection of related sources that share a common service account and configuration. Source groups are created through the **Connect Source** wizard, which handles source creation, scan configuration, and scheduling in a single workflow. + +- **File Server** source groups can contain multiple servers (for example, all file servers in a department) +- **Active Directory** source groups can contain multiple domain controllers +- **Entra ID** source groups contain a single source (one Azure AD tenant) + +Source groups simplify management by letting you configure shared settings (service account, domain, scan options) once and apply them to all sources in the group. + +## Service Accounts + +A **service account** stores credentials used to authenticate with data sources and identity providers. Supported credential types include: + +- **Username / Password** — For Active Directory, CIFS/SMB file shares, and local groups +- **Client credentials (OAuth2)** — For Entra ID +- **Certificate** — For SharePoint Online + +Service accounts are managed in **Configuration** > **Service Accounts** and can be shared across multiple sources. + +## Connectors + +A **connector** is the component that performs the actual work of communicating with a source. Each source type has a corresponding connector that handles: + +- **Test connection** — Validates that credentials and network connectivity are correct +- **Access scan / sync** — Enumerates files, folders, permissions, or identities +- **Get object** — Retrieves specific objects or metadata + +Connectors are executed as Kubernetes Jobs and managed by the Connector API. + +## Scans + +A **scan** defines what to analyze and how. Access Analyzer supports several scan types: + +- **Access scans** — Enumerate files, folders, and permissions on data sources to identify who has access to what +- **Sensitive data scans** — Classify file contents against detection patterns to find PII, credentials, PHI, and financial records +- **Identity sync scans** — Synchronize users, groups, and roles from IAM sources (Active Directory Inventory, Entra ID Users/Groups/Roles) +- **Local Users and Groups scans** — Collect local account data from file servers (auto-created when an access scan is enabled) + +Scans are configured during the [Connect Source wizard](/docs/accessanalyzer/1_0/gettingstarted/firstscan/configuringscan) and can be run on demand or scheduled with a cron expression. Each scan run produces a **scan execution** record with status, duration, and results. + +## Identities and Entitlements + +- **Identity** — A user or group account from an IAM source (Active Directory, Entra ID, or local groups) +- **Entitlement** — A permission or access right granted to an identity on a data source (for example, read access to a file share) + +Access Analyzer maps identities to entitlements to show effective permissions and identify overly permissive access. + +## Sensitive Data Patterns + +A **pattern** is a detection rule used during sensitive data scans. Patterns match file content against regular expressions or classification models. Built-in patterns cover: + +- **PII** — Personally identifiable information (names, addresses, SSNs, etc.) +- **Credentials** — Passwords, API keys, tokens, and connection strings +- **PHI** — Protected health information +- **Financial Records** — Credit card numbers, bank accounts, financial data + +Patterns are organized into **taxonomies** — hierarchical groups of classification rules mapped to compliance frameworks (GDPR, CCPA, HIPAA, PCI DSS, GLBA, CMMC). + +## Dashboards + +**Dashboards** are pre-built Metabase visualizations that provide a summary view of your data security posture, including: + +- Sensitive data exposure by type and framework +- Access permission distribution +- Identity and group analysis + +Dashboards are embedded in the Access Analyzer web interface with single sign-on. diff --git a/docs/accessanalyzer/1.0/overview/overview.md b/docs/accessanalyzer/1.0/overview/overview.md new file mode 100644 index 0000000000..c74a5290d8 --- /dev/null +++ b/docs/accessanalyzer/1.0/overview/overview.md @@ -0,0 +1,36 @@ +--- +title: "What is Access Analyzer" +description: "Introduction to Netwrix Access Analyzer and its capabilities" +sidebar_position: 10 +--- + +# What is Access Analyzer + +Netwrix Access Analyzer is a Data Security Posture Management (DSPM) platform that discovers, classifies, and secures sensitive data across your organization's file systems and cloud services. It provides visibility into who has access to what data, identifies overly permissive access, and detects sensitive data exposure. + +## Core Capabilities + +- **Data Source Discovery** — Connect to file shares (CIFS/SMB), SharePoint Online sites, and other data repositories to inventory content and access permissions +- **Identity and Access Analysis** — Synchronize with Active Directory, Entra ID, and local groups to map identities, group memberships, and effective permissions +- **Sensitive Data Detection** — Scan files for PII, credentials, PHI, and financial records using built-in patterns and custom regex rules, with compliance mappings to GDPR, CCPA, HIPAA, PCI DSS, GLBA, and CMMC +- **Dashboards and Reporting** — View findings through embedded Metabase dashboards for data security posture, Active Directory insights, and sensitive data exposure +- **Audit Trail** — Maintain a full audit log of user actions and system events + +## How It Works + +1. **Configure data sources** — Add file shares, cloud services, and identity providers as data sources, each with an associated service account for authentication +2. **Run scans** — Create access scans to enumerate permissions and sensitive data scans to classify content +3. **Review findings** — Analyze results through dashboards, reports, and the scan execution history +4. **Take action** — Identify and remediate overly permissive access, exposed sensitive data, and policy violations + +## Deployment Model + +Access Analyzer is deployed as a self-contained Kubernetes cluster on a single Linux VM. A one-command installer provisions all required infrastructure — including K3s, ArgoCD, databases, and application services. Updates are managed automatically through ArgoCD GitOps. + +For installation instructions, see [Installation](/docs/accessanalyzer/1_0/install/overview). + +## What's Next + +- [Architecture Overview](/docs/accessanalyzer/1_0/overview/architecture) — Understand the platform components and how they interact +- [Key Concepts](/docs/accessanalyzer/1_0/overview/keyconcepts) — Learn the terminology used throughout Access Analyzer +- [Getting Started](/docs/accessanalyzer/1_0/gettingstarted/overview) — Begin configuring your first data source and scan diff --git a/docs/accessanalyzer/1.0/requirements/_category_.json b/docs/accessanalyzer/1.0/requirements/_category_.json new file mode 100644 index 0000000000..2047289ac1 --- /dev/null +++ b/docs/accessanalyzer/1.0/requirements/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Requirements", + "position": 30, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/requirements/connectors/_category_.json b/docs/accessanalyzer/1.0/requirements/connectors/_category_.json new file mode 100644 index 0000000000..4616c42c8c --- /dev/null +++ b/docs/accessanalyzer/1.0/requirements/connectors/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Connector Requirements", + "position": 30, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "cifs" + } +} diff --git a/docs/accessanalyzer/1.0/requirements/connectors/activedirectory.md b/docs/accessanalyzer/1.0/requirements/connectors/activedirectory.md new file mode 100644 index 0000000000..2ef3c03a17 --- /dev/null +++ b/docs/accessanalyzer/1.0/requirements/connectors/activedirectory.md @@ -0,0 +1,45 @@ +--- +title: "Active Directory" +description: "LDAP connectivity, service account permissions, and network ports" +sidebar_position: 30 +--- + +# Active Directory + +The Active Directory connector synchronizes users, groups, and group memberships from Active Directory into Access Analyzer. It uses the LDAP protocol for communication. + +## Network Requirements + +| Port | Protocol | Direction | Description | +| --- | --- | --- | --- | +| 389 | TCP | Access Analyzer → Domain Controller | LDAP | +| 636 | TCP | Access Analyzer → Domain Controller | LDAPS (LDAP over SSL) | + +## Service Account Requirements + +The connector requires a domain service account with the following: + +| Requirement | Details | +| --- | --- | +| **Account type** | Domain user account | +| **Authentication** | Username and password | +| **Minimum permissions** | Read access to directory objects (users, groups, OUs) | +| **Recommended group** | Domain Users (or equivalent read-only access) | + +:::note +The service account does not require Domain Admin or any write permissions. Read-only access to directory objects is sufficient for identity synchronization. +::: + +## Credential Type + +| Field | Value | +| --- | --- | +| **Type** | Username / Password | +| **Username format** | `DOMAIN\username` or `username@domain.com` | + +## Connector Capabilities + +| Operation | Description | +| --- | --- | +| **Test connection** | Validates LDAP connectivity and credential authentication | +| **Sync** | Full synchronization of users, groups, and group memberships | diff --git a/docs/accessanalyzer/1.0/requirements/connectors/cifs.md b/docs/accessanalyzer/1.0/requirements/connectors/cifs.md new file mode 100644 index 0000000000..a5ade15dbd --- /dev/null +++ b/docs/accessanalyzer/1.0/requirements/connectors/cifs.md @@ -0,0 +1,52 @@ +--- +title: "CIFS / SMB File Share" +description: "Supported platforms, permissions, and network ports for CIFS/SMB scanning" +sidebar_position: 10 +--- + +# CIFS / SMB File Share + +The CIFS/SMB connector scans Windows file shares to enumerate files, folders, and access permissions. It supports SMBv2 and SMBv3 protocols with concurrent scanning workers. + +## Network Requirements + +| Port | Protocol | Direction | Description | +| --- | --- | --- | --- | +| 445 | TCP | Access Analyzer → File Server | SMB file sharing | + +## Service Account Requirements + +| Requirement | Details | +| --- | --- | +| **Account type** | Domain or local user account on the file server | +| **Authentication** | Username and password | +| **Minimum permissions** | Read access and list permissions on target shares | +| **Domain** | Required if the file server is domain-joined | + +:::note +The service account needs read-only access to the shares and folders being scanned. It does not require write, modify, or administrative permissions. +::: + +## Credential Type + +| Field | Value | +| --- | --- | +| **Type** | Username / Password | +| **Username format** | `DOMAIN\username` or local account name | + +## Connector Capabilities + +| Operation | Description | +| --- | --- | +| **Test connection** | Validates SMB connectivity and authentication | +| **Access scan** | Enumerates files, folders, and permissions with configurable worker concurrency (1–20) | +| **Get object** | Retrieves specific file or folder metadata | + +## Scan Configuration Options + +| Option | Description | +| --- | --- | +| **Share filtering** | Include or exclude specific shares | +| **Scan depth** | Maximum folder depth to traverse | +| **Worker concurrency** | Number of parallel scanning threads (1–20) | +| **Pause / Resume** | Scans can be paused and resumed | diff --git a/docs/accessanalyzer/1.0/requirements/connectors/entraid.md b/docs/accessanalyzer/1.0/requirements/connectors/entraid.md new file mode 100644 index 0000000000..11dfb77943 --- /dev/null +++ b/docs/accessanalyzer/1.0/requirements/connectors/entraid.md @@ -0,0 +1,54 @@ +--- +title: "Entra ID" +description: "Azure App Registration, Graph API permissions, and OAuth2 credentials" +sidebar_position: 40 +--- + +# Entra ID + +The Entra ID connector validates connectivity to Microsoft Entra ID (formerly Azure Active Directory) using OAuth2 client credentials. + +:::note +In Access Analyzer v1.0, the Entra ID connector supports **test connection only**. Full identity synchronization is not available in this release. +::: + +## Network Requirements + +| Port | Protocol | Direction | Description | +| --- | --- | --- | --- | +| 443 | TCP | Access Analyzer → Microsoft identity platform | HTTPS | + +## Azure App Registration + +An Azure AD (Entra ID) app registration is required. + +### Required API Permissions + +| Permission | Type | Description | +| --- | --- | --- | +| `User.Read.All` | Application | Read all user profiles (for future sync capability) | +| `Group.Read.All` | Application | Read all group memberships (for future sync capability) | + +### Registration Steps + +1. Sign in to the [Azure portal](https://portal.azure.com) and navigate to **Microsoft Entra ID** > **App registrations** +2. Click **New registration** and provide a name +3. Under **API permissions**, add the required Microsoft Graph application permissions +4. Grant admin consent for the permissions +5. Under **Certificates & secrets**, create a client secret +6. Note the **Application (client) ID**, **Tenant ID**, and **Client Secret** + +## Credential Type + +| Field | Value | +| --- | --- | +| **Type** | OAuth2 Client Credentials | +| **Client ID** | Application (client) ID | +| **Client Secret** | Client secret value | +| **Tenant ID** | Directory (tenant) ID | + +## Connector Capabilities + +| Operation | Description | +| --- | --- | +| **Test connection** | Validates OAuth2 authentication and Graph API connectivity | diff --git a/docs/accessanalyzer/1.0/requirements/connectors/localgroups.md b/docs/accessanalyzer/1.0/requirements/connectors/localgroups.md new file mode 100644 index 0000000000..ac5efd6ad9 --- /dev/null +++ b/docs/accessanalyzer/1.0/requirements/connectors/localgroups.md @@ -0,0 +1,52 @@ +--- +title: "Local Groups" +description: "PowerShell Remoting and target machine permissions" +sidebar_position: 50 +--- + +# Local Groups + +The Local Groups connector enumerates local users and group memberships on Windows machines using PowerShell Remoting (WinRM). + +## Network Requirements + +| Port | Protocol | Direction | Description | +| --- | --- | --- | --- | +| 5985 | TCP | Access Analyzer → Target Machine | WinRM over HTTP | +| 5986 | TCP | Access Analyzer → Target Machine | WinRM over HTTPS | + +## Service Account Requirements + +| Requirement | Details | +| --- | --- | +| **Account type** | Local administrator or member of Remote Management Users group | +| **Authentication** | Username and password | +| **WinRM** | PowerShell Remoting must be enabled on target machines | + +## Enabling WinRM on Target Machines + +PowerShell Remoting must be enabled on each target machine: + +```powershell +Enable-PSRemoting -Force +``` + +For domain-joined machines, this can be configured via Group Policy: + +1. Open **Group Policy Management** +2. Navigate to **Computer Configuration** > **Administrative Templates** > **Windows Components** > **Windows Remote Management (WinRM)** > **WinRM Service** +3. Enable **Allow remote server management through WinRM** + +## Credential Type + +| Field | Value | +| --- | --- | +| **Type** | Username / Password | +| **Username format** | `MACHINE\username` or `DOMAIN\username` | + +## Connector Capabilities + +| Operation | Description | +| --- | --- | +| **Test connection** | Validates WinRM connectivity and authentication | +| **Sync** | Enumerates local users, groups, and group memberships | diff --git a/docs/accessanalyzer/1.0/requirements/connectors/sharepointonline.md b/docs/accessanalyzer/1.0/requirements/connectors/sharepointonline.md new file mode 100644 index 0000000000..4e06241002 --- /dev/null +++ b/docs/accessanalyzer/1.0/requirements/connectors/sharepointonline.md @@ -0,0 +1,57 @@ +--- +title: "SharePoint Online" +description: "Azure App Registration, Graph API permissions, and certificate authentication" +sidebar_position: 20 +--- + +# SharePoint Online + +The SharePoint Online connector scans SharePoint sites to enumerate content and access permissions using the Microsoft Graph API with certificate-based authentication. + +## Network Requirements + +| Port | Protocol | Direction | Description | +| --- | --- | --- | --- | +| 443 | TCP | Access Analyzer → Microsoft Graph API | HTTPS | + +## Azure App Registration + +An Azure AD (Entra ID) app registration is required for SharePoint Online connectivity. + +### Required API Permissions + +| Permission | Type | Description | +| --- | --- | --- | +| `Sites.Read.All` | Application | Read items in all site collections | + +### Registration Steps + +1. Sign in to the [Azure portal](https://portal.azure.com) and navigate to **Microsoft Entra ID** > **App registrations** +2. Click **New registration** and provide a name (for example, `Netwrix Access Analyzer - SharePoint`) +3. Under **API permissions**, add the **Microsoft Graph** application permission `Sites.Read.All` +4. Grant admin consent for the permission +5. Under **Certificates & secrets**, upload a certificate (`.cer` or `.pem` public key) +6. Note the **Application (client) ID** and **Tenant ID** + +## Credential Type + +| Field | Value | +| --- | --- | +| **Type** | Certificate | +| **Client ID** | Application (client) ID from the app registration | +| **Tenant ID** | Directory (tenant) ID | +| **Certificate** | Private key file (`.pem`) corresponding to the uploaded public key | + +## Connector Capabilities + +| Operation | Description | +| --- | --- | +| **Test connection** | Validates Graph API connectivity and certificate authentication | +| **Access scan** | Enumerates SharePoint sites, document libraries, files, and permissions | +| **Get object** | Retrieves specific site or document metadata | + +## Scan Configuration Options + +| Option | Description | +| --- | --- | +| **Site filtering** | Include or exclude specific SharePoint sites | diff --git a/docs/accessanalyzer/1.0/requirements/database/_category_.json b/docs/accessanalyzer/1.0/requirements/database/_category_.json new file mode 100644 index 0000000000..32e43edc04 --- /dev/null +++ b/docs/accessanalyzer/1.0/requirements/database/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Database Requirements", + "position": 20, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "postgresql" + } +} diff --git a/docs/accessanalyzer/1.0/requirements/database/clickhouse.md b/docs/accessanalyzer/1.0/requirements/database/clickhouse.md new file mode 100644 index 0000000000..868c10e9da --- /dev/null +++ b/docs/accessanalyzer/1.0/requirements/database/clickhouse.md @@ -0,0 +1,30 @@ +--- +title: "ClickHouse" +description: "ClickHouse version and configuration" +sidebar_position: 20 +--- + +# ClickHouse + +ClickHouse is a columnar analytics database used by Access Analyzer for scan results, reporting data, and observability (OpenTelemetry traces and logs). + +## Version + +| Component | Value | +| --- | --- | +| **ClickHouse version** | 25.8.13 | +| **Namespace** | `access-analyzer` | +| **HTTP interface port** | 8123 | +| **Native protocol port** | 9000 | + +## Provisioning + +ClickHouse is **automatically provisioned** by the installer. No manual setup is required. + +Database passwords are auto-generated and stored as Kubernetes secrets. + +## Data Stored + +- Scan results and analytics data +- OpenTelemetry traces and logs (via the `access_analyzer_logs` database) +- Reporting and dashboard data queried by Metabase diff --git a/docs/accessanalyzer/1.0/requirements/database/postgresql.md b/docs/accessanalyzer/1.0/requirements/database/postgresql.md new file mode 100644 index 0000000000..4e5f9dba79 --- /dev/null +++ b/docs/accessanalyzer/1.0/requirements/database/postgresql.md @@ -0,0 +1,40 @@ +--- +title: "PostgreSQL" +description: "PostgreSQL version and configuration" +sidebar_position: 10 +--- + +# PostgreSQL + +PostgreSQL serves as the primary relational database for Access Analyzer, storing configuration, user accounts, scan metadata, connector state, and application data. + +## Version + +| Component | Value | +| --- | --- | +| **PostgreSQL version** | 14.18 | +| **Namespace** | `access-analyzer` | + +## Provisioning + +PostgreSQL is **automatically provisioned** by the installer. No manual database setup, schema creation, or user configuration is required. + +The installer creates the following database users during deployment: + +| User | Purpose | +| --- | --- | +| `postgres` | Superuser for administrative tasks | +| `connector_readonly` | Read-only access for connector queries | +| `connector_execution_update` | Write access for connector execution state | +| `connector_state_readwrite` | Read/write access for connector state management | + +All database passwords are auto-generated by the `dspm-utility` secret initialization process and stored as Kubernetes secrets. + +## Data Stored + +- User accounts and authentication +- Source and scan configuration +- Service accounts (encrypted credentials) +- Connector state and execution metadata +- Application settings and feature flags +- Audit log entries diff --git a/docs/accessanalyzer/1.0/requirements/database/redis.md b/docs/accessanalyzer/1.0/requirements/database/redis.md new file mode 100644 index 0000000000..9cc26151cb --- /dev/null +++ b/docs/accessanalyzer/1.0/requirements/database/redis.md @@ -0,0 +1,43 @@ +--- +title: "Redis" +description: "Redis version and configuration" +sidebar_position: 30 +--- + +# Redis + +Redis provides in-memory caching, session storage, and job queue management for Access Analyzer. + +## Version + +| Component | Value | +| --- | --- | +| **Redis version** | 8.4.0 | +| **Namespace** | `access-analyzer` | +| **Port** | 6379 | + +## Provisioning + +Redis is **automatically provisioned** by the installer. No manual setup is required. + +## Data Stored + +| Function | Description | +| --- | --- | +| **User sessions** | Session data for authenticated users (with IP validation and configurable TTL) | +| **Sidekiq job queues** | Background job processing for scans, syncs, mailers, and system tasks | +| **Application cache** | Frequently accessed data for reduced database load | + +## Job Queues + +Redis backs the Sidekiq job processing system, which uses the following queues: + +| Queue | Purpose | +| --- | --- | +| `critical` | High-priority system operations | +| `scans` | Scan execution jobs | +| `syncs` | Identity synchronization jobs | +| `scheduler` | Scheduled job dispatch | +| `default` | General-purpose jobs | +| `mailers` | Email notification delivery | +| `low` | Low-priority background tasks | diff --git a/docs/accessanalyzer/1.0/requirements/overview.md b/docs/accessanalyzer/1.0/requirements/overview.md new file mode 100644 index 0000000000..84fa865f34 --- /dev/null +++ b/docs/accessanalyzer/1.0/requirements/overview.md @@ -0,0 +1,35 @@ +--- +title: "Requirements" +description: "System, database, and connector requirements for Access Analyzer" +sidebar_position: 1 +--- + +# Requirements + +This section covers all prerequisites for deploying and operating Netwrix Access Analyzer. + +## System Requirements + +The Access Analyzer VM must meet minimum hardware, operating system, and kernel requirements. The installer validates these automatically during [preflight checks](/docs/accessanalyzer/1_0/install/preflight). + +- [Kubernetes and Operating System](/docs/accessanalyzer/1_0/requirements/system/kubernetes) — OS version, kernel, and K3s details +- [Hardware and Resource Allocation](/docs/accessanalyzer/1_0/requirements/system/hardware) — CPU, memory, disk, and virtualization +- [Network and Port Requirements](/docs/accessanalyzer/1_0/requirements/system/network) — Outbound endpoints, internal ports, and firewall rules + +## Database Requirements + +All databases are automatically provisioned by the installer. No manual database setup is required. + +- [PostgreSQL](/docs/accessanalyzer/1_0/requirements/database/postgresql) — Primary relational database +- [ClickHouse](/docs/accessanalyzer/1_0/requirements/database/clickhouse) — Analytics and observability database +- [Redis](/docs/accessanalyzer/1_0/requirements/database/redis) — Session cache and job queues + +## Connector Requirements + +Each connector type has specific requirements for authentication, network access, and permissions on the target system. + +- [CIFS / SMB File Share](/docs/accessanalyzer/1_0/requirements/connectors/cifs) — SMB file share scanning +- [SharePoint Online](/docs/accessanalyzer/1_0/requirements/connectors/sharepointonline) — SharePoint site scanning +- [Active Directory](/docs/accessanalyzer/1_0/requirements/connectors/activedirectory) — AD identity synchronization +- [Entra ID](/docs/accessanalyzer/1_0/requirements/connectors/entraid) — Entra ID connection testing +- [Local Groups](/docs/accessanalyzer/1_0/requirements/connectors/localgroups) — Local group enumeration diff --git a/docs/accessanalyzer/1.0/requirements/system/_category_.json b/docs/accessanalyzer/1.0/requirements/system/_category_.json new file mode 100644 index 0000000000..950fb05a5f --- /dev/null +++ b/docs/accessanalyzer/1.0/requirements/system/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "System Requirements", + "position": 10, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "kubernetes" + } +} diff --git a/docs/accessanalyzer/1.0/requirements/system/hardware.md b/docs/accessanalyzer/1.0/requirements/system/hardware.md new file mode 100644 index 0000000000..7787c810de --- /dev/null +++ b/docs/accessanalyzer/1.0/requirements/system/hardware.md @@ -0,0 +1,84 @@ +--- +title: "Hardware and Resource Allocation" +description: "CPU, memory, storage, and virtualization requirements" +sidebar_position: 20 +--- + +# Hardware and Resource Allocation + +Access Analyzer is deployed on a single Linux virtual machine. This page details the hardware requirements and virtualization configuration. + +## Deployment Sizing + +| Size | CPU | Memory | Disk | Use Case | +| --- | --- | --- | --- | --- | +| **Small** | 2 vCPUs (4 recommended) | 8 GB (16 GB recommended) | 20 GB free (50 GB recommended) | Evaluation and small environments | +| **Medium** | 8 vCPUs | 32 GB | 100 GB SSD | Mid-size environments | +| **Large** | 16 vCPUs | 64 GB | 500 GB SSD | Large enterprise environments | + +All sizes require SSD or NVMe storage for optimal database performance. + +## Disk Space by Directory + +| Path | Minimum Free Space | Purpose | +| --- | --- | --- | +| `/` | 20 GB | Root filesystem | +| `/var` | 20 GB | K3s data, containers, logs | +| `/var/lib` | 20 GB | K3s data directory | +| `/var/log` | 5 GB | System and application logs | +| `/etc` | 1 GB | Configuration files | + +## Virtualization Requirements + +When running on a hypervisor, the following must be supported: + +| Requirement | Details | +| --- | --- | +| **Linux namespaces** | NET, PID, IPC, UTS, MNT, USER | +| **Control groups** | cgroups v1 or v2 with memory and CPU controllers | +| **Overlay filesystem** | Kernel module for container layers | +| **iptables** | Kubernetes networking | + +## Hypervisor Configuration + +Configure **static memory allocation** for the Access Analyzer VM. Dynamic or ballooned memory can cause resource underestimation and out-of-memory conditions. + +### VMware vSphere / ESXi + +Disable memory ballooning: + +``` +sched.mem.pshare.enable = "FALSE" +mem.balloon.enable = "FALSE" +``` + +Set these in **VM Settings** > **VM Options** > **Advanced** > **Edit Configuration**. + +### Microsoft Hyper-V + +Use static memory: + +```powershell +Set-VMMemory -VMName "" -DynamicMemoryEnabled $false -StartupBytes 16GB +``` + +### KVM / QEMU + +Use hugepages: + +```xml + + + +``` + +## Swap + +| System Memory | Recommendation | +| --- | --- | +| 16 GB or more | Swap is optional | +| Less than 16 GB | 2–4 GB swap recommended to prevent OOM during container pulls | + +## Resource Scaling + +The installer supports a `--size` flag (1–10) that scales memory thresholds by the specified multiplier. For example, `--size 2` doubles the minimum and recommended memory requirements. See [Environment Variables](/docs/accessanalyzer/1_0/install/environmentvariables). diff --git a/docs/accessanalyzer/1.0/requirements/system/kubernetes.md b/docs/accessanalyzer/1.0/requirements/system/kubernetes.md new file mode 100644 index 0000000000..fb62a394f0 --- /dev/null +++ b/docs/accessanalyzer/1.0/requirements/system/kubernetes.md @@ -0,0 +1,53 @@ +--- +title: "Kubernetes and Operating System" +description: "OS version, kernel requirements, and K3s Kubernetes details" +sidebar_position: 10 +--- + +# Kubernetes and Operating System + +Access Analyzer uses K3s, a lightweight Kubernetes distribution, which is automatically deployed by the installer. No manual Kubernetes setup is required. + +## Operating System + +| Requirement | Value | +| --- | --- | +| **Distribution** | Ubuntu 24.04 LTS | +| **Architecture** | x86_64 (amd64) | +| **Kernel version** | 5.15 or later | + +:::note +Other Linux distributions may work but are not officially tested or supported. Ubuntu 24.04 LTS is the recommended and validated platform. +::: + +## K3s Kubernetes + +| Component | Version | +| --- | --- | +| **K3s** | v1.33.4+k3s1 | +| **Kubeconfig mode** | `644` | +| **Secrets encryption** | Enabled (at rest) | +| **Service name** | `k3s-dspm` | + +K3s is installed and managed automatically by the Access Analyzer installer. The `kubectl` command is available immediately after installation for cluster management. + +## Kernel Features + +The following kernel features must be available. The installer [preflight checks](/docs/accessanalyzer/1_0/install/preflight) validate these automatically: + +| Feature | Description | +| --- | --- | +| **cgroups v1 or v2** | Memory and CPU controllers required for container resource management | +| **Overlay filesystem** | `overlay` kernel module for container image layers | +| **Linux namespaces** | NET, PID, IPC, UTS, MNT, USER for container isolation | +| **iptables** | Required for Kubernetes networking and service routing | + +## ArgoCD + +| Component | Version | +| --- | --- | +| **ArgoCD** | v3.2.0 | +| **Namespace** | `argocd` | +| **UI port** | 8090 (via port-forward) | + +ArgoCD is deployed automatically and manages the lifecycle of all Access Analyzer application components through GitOps. diff --git a/docs/accessanalyzer/1.0/requirements/system/network.md b/docs/accessanalyzer/1.0/requirements/system/network.md new file mode 100644 index 0000000000..f3c04090b4 --- /dev/null +++ b/docs/accessanalyzer/1.0/requirements/system/network.md @@ -0,0 +1,64 @@ +--- +title: "Network and Port Requirements" +description: "Required network ports, outbound endpoints, and firewall rules" +sidebar_position: 30 +--- + +# Network and Port Requirements + +Access Analyzer requires outbound internet access during installation and operation, and specific internal ports for service communication. + +## Outbound Endpoints (Internet) + +The following endpoints must be reachable over HTTPS (port 443): + +| Endpoint | Purpose | When Required | +| --- | --- | --- | +| `get.k3s.io` | K3s installer download | Installation only | +| `raw.githubusercontent.com` | ArgoCD manifests | Installation only | +| `oci.pkg.keygen.sh` | Netwrix OCI registry (Helm charts, application images) | Installation and updates | +| `docker.io` / `docker.com` | Container base images | Installation and updates | + +## Internal Ports + +These ports are used within the Access Analyzer VM for service-to-service communication: + +| Port | Protocol | Service | Description | +| --- | --- | --- | --- | +| 443 | TCP | Traefik | HTTPS ingress for web UI and API | +| 6443 | TCP | K3s API | Kubernetes API server | +| 8090 | TCP | ArgoCD | ArgoCD UI (via port-forward) | +| 5432 | TCP | PostgreSQL | Database connections | +| 8123 | TCP | ClickHouse | HTTP interface | +| 9000 | TCP | ClickHouse | Native protocol | +| 6379 | TCP | Redis | Cache and queue connections | + +:::note +All internal ports are bound to the local cluster network. Only port 443 (Traefik) is exposed externally for the web interface. +::: + +## Connector Network Requirements + +Depending on the connectors you configure, the Access Analyzer VM must also have outbound access to your data sources: + +| Connector | Target Port | Protocol | Notes | +| --- | --- | --- | --- | +| CIFS / SMB | 445 | TCP | SMB file shares | +| Active Directory | 389 / 636 | TCP | LDAP / LDAPS | +| SharePoint Online | 443 | TCP | Microsoft Graph API | +| Entra ID | 443 | TCP | Microsoft identity platform | +| Local Groups | 5985 / 5986 | TCP | WinRM (HTTP / HTTPS) | + +## Proxy Configuration + +If outbound traffic is routed through a proxy, set the following environment variables before running the installer: + +```bash +export HTTP_PROXY="http://:" +export HTTPS_PROXY="http://:" +export NO_PROXY="localhost,127.0.0.1,10.0.0.0/8" +``` + +## Firewall Configuration + +See [Network Configuration](/docs/accessanalyzer/1_0/install/network) for firewall rule examples for Azure, AWS, and on-premises environments. diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/_category_.json b/docs/accessanalyzer/1.0/sensitivedatadiscovery/_category_.json new file mode 100644 index 0000000000..6bf6249468 --- /dev/null +++ b/docs/accessanalyzer/1.0/sensitivedatadiscovery/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Sensitive Data Discovery", + "position": 70, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/overview.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/overview.md new file mode 100644 index 0000000000..f534a637e7 --- /dev/null +++ b/docs/accessanalyzer/1.0/sensitivedatadiscovery/overview.md @@ -0,0 +1,32 @@ +--- +title: "Sensitive Data Discovery" +description: "Discover and classify sensitive data across your environment" +sidebar_position: 1 +--- + +# Sensitive Data Discovery + +Sensitive Data Discovery (SDD) in Netwrix Access Analyzer identifies and classifies sensitive information across your connected data sources. The platform uses two complementary detection methods: the Netwrix Data Classification SDK and custom regex pattern matching. + +## Workflow + +Follow these steps to discover sensitive data in your environment: + +1. **Configure detection patterns** — Select from [built-in patterns](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/builtinpatterns) or [create custom regex patterns](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/custompatterns) to define what constitutes sensitive data. +2. **Organize patterns into groups** — Use [pattern groups](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/patterngroups) to logically categorize your detection patterns. +3. **Map to compliance frameworks** — Configure [taxonomy groups](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/taxonomygroups) and [classification rules](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/classificationrules) to align findings with regulatory requirements. +4. **Run a scan** — [Execute a sensitive data scan](/docs/accessanalyzer/1_0/sensitivedatadiscovery/runningscan) against your target data sources. +5. **Review results** — Analyze [match counts](/docs/accessanalyzer/1_0/sensitivedatadiscovery/reviewingresults/matchcounts) and [classification breakdowns](/docs/accessanalyzer/1_0/sensitivedatadiscovery/reviewingresults/classificationbreakdown) to understand your data risk posture. + +## Supported Data Types + +| Category | Examples | +| --- | --- | +| PII | Social Security numbers, names, addresses, email addresses | +| Credentials | Passwords, API keys, authentication tokens | +| PHI | Medical records, health data, insurance identifiers | +| Financial Records | Credit card numbers, bank account details | + +:::note +Sensitive data scans are configured during the scan creation wizard. Ensure your detection patterns and taxonomy mappings are in place before running your first scan. +::: diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/_category_.json b/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/_category_.json new file mode 100644 index 0000000000..868656ec39 --- /dev/null +++ b/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Configuring Patterns", + "position": 20, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "builtinpatterns" + } +} diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/builtinpatterns.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/builtinpatterns.md new file mode 100644 index 0000000000..0653231675 --- /dev/null +++ b/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/builtinpatterns.md @@ -0,0 +1,34 @@ +--- +title: "Built-in Patterns" +description: "Pre-configured patterns for PII, PCI, SSN, and more" +sidebar_position: 10 +--- + +# Built-in Patterns + +Netwrix Access Analyzer ships with a library of pre-configured detection patterns that identify common categories of sensitive data. These built-in patterns use the Netwrix Data Classification SDK and are ready to use without additional configuration. + +## Pattern Categories + +| Category | Description | Examples | +| --- | --- | --- | +| PII | Personally identifiable information | Social Security numbers, full names, mailing addresses, email addresses, phone numbers | +| Credentials | Authentication and access secrets | Passwords, API keys, tokens, private keys, connection strings | +| PHI | Protected health information | Medical record numbers, health plan IDs, diagnosis codes, lab results | +| Financial Records | Payment and banking data | Credit card numbers (PAN), bank account and routing numbers, tax IDs | + +## How Built-in Patterns Work + +Built-in patterns leverage two detection methods: + +- **Netwrix Data Classification SDK** — A C#/.NET-based engine that applies advanced heuristics and contextual analysis beyond simple pattern matching. +- **Regex pattern matching** — Standard regular expressions tuned for high-accuracy detection of structured data formats such as SSNs, credit card numbers, and IBANs. + +:::note +Built-in patterns cannot be edited directly. To modify detection behavior, create a [custom pattern](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/custompatterns) and organize it into a [pattern group](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/patterngroups). +::: + +## Next Steps + +- [Create custom regex patterns](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/custompatterns) for organization-specific data formats +- [Organize patterns into groups](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/patterngroups) for streamlined scan configuration diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/custompatterns.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/custompatterns.md new file mode 100644 index 0000000000..8645e34568 --- /dev/null +++ b/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/custompatterns.md @@ -0,0 +1,47 @@ +--- +title: "Creating Custom Regex Patterns" +description: "Define custom regex patterns for sensitive data detection" +sidebar_position: 20 +--- + +# Creating Custom Regex Patterns + +Custom regex patterns allow you to extend sensitive data detection beyond the built-in library. Define patterns that match organization-specific data formats such as internal account numbers, proprietary identifiers, or region-specific document formats. + +## Creating a Custom Pattern + +To create a custom regex pattern: + +1. Navigate to the **Sensitive Data Discovery** section in Access Analyzer. +2. Select **Patterns** and click **Add Pattern**. +3. Provide a **Name** and optional **Description** for the pattern. +4. Enter the **Regex Expression** that defines the match criteria. +5. Select the appropriate **Category** (PII, Credentials, PHI, or Financial Records). +6. Click **Save** to register the pattern. + +:::note +Custom patterns can also be added programmatically via the Access Analyzer API. Refer to the API documentation for endpoint details and payload format. +::: + +## Regex Best Practices + +- **Be specific** — Overly broad patterns increase false positives. Use anchors, character classes, and quantifiers to narrow matches. +- **Test before deploying** — Validate your regex against sample data to confirm it captures the intended formats without excessive noise. +- **Use named groups** — Where supported, named capture groups improve readability and facilitate downstream processing. + +## Example + +A pattern to detect a custom internal employee ID formatted as `EMP-` followed by six digits: + +``` +EMP-\d{6} +``` + +:::warning +Poorly constructed regex patterns may degrade scan performance. Avoid unbounded quantifiers and excessive backtracking in pattern definitions. +::: + +## Next Steps + +- [Organize patterns into groups](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/patterngroups) for easier management +- [Map patterns to compliance frameworks](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/taxonomygroups) using taxonomy groups diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/patterngroups.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/patterngroups.md new file mode 100644 index 0000000000..9643c03154 --- /dev/null +++ b/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/patterngroups.md @@ -0,0 +1,39 @@ +--- +title: "Pattern Groups" +description: "Organizing patterns into logical groups" +sidebar_position: 30 +--- + +# Pattern Groups + +Pattern groups organize individual detection patterns into logical collections. Grouping patterns by category or purpose simplifies scan configuration and makes it easier to apply consistent detection policies across multiple scans. + +## How Pattern Groups Work + +A pattern group is a named container that holds one or more detection patterns (built-in or custom). When you configure a sensitive data scan, you select pattern groups rather than individual patterns, which reduces configuration complexity. + +Common grouping strategies include: + +- **By data type** — Group all PII patterns together, all credential patterns together, and so on. +- **By compliance framework** — Group patterns that satisfy a specific regulation such as HIPAA or PCI DSS. +- **By business unit** — Group patterns relevant to a particular department or data domain. + +## Managing Pattern Groups + +To create or edit a pattern group: + +1. Navigate to **Sensitive Data Discovery** > **Patterns**. +2. Select the **Pattern Groups** tab. +3. Click **Add Group** to create a new group, or select an existing group to edit it. +4. Provide a **Name** and optional **Description**. +5. Add or remove patterns from the group using the pattern selector. +6. Click **Save**. + +:::note +A single pattern can belong to multiple groups. Changes to a pattern are reflected in all groups that reference it. +::: + +## Next Steps + +- [Configure taxonomy groups](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/taxonomygroups) to map pattern groups to compliance frameworks +- [Run a sensitive data scan](/docs/accessanalyzer/1_0/sensitivedatadiscovery/runningscan) using your configured pattern groups diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/_category_.json b/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/_category_.json new file mode 100644 index 0000000000..8d68d0c5ea --- /dev/null +++ b/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Reviewing Results", + "position": 50, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "matchcounts" + } +} diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/classificationbreakdown.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/classificationbreakdown.md new file mode 100644 index 0000000000..74a5711b20 --- /dev/null +++ b/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/classificationbreakdown.md @@ -0,0 +1,43 @@ +--- +title: "Classification Breakdown" +description: "Analyzing results by classification category" +sidebar_position: 20 +--- + +# Classification Breakdown + +The classification breakdown view organizes sensitive data scan results by taxonomy group and compliance framework. This view helps you assess regulatory exposure and prioritize remediation efforts based on the frameworks most relevant to your organization. + +## Viewing the Breakdown + +To access the classification breakdown: + +1. Navigate to the **Scans** section and select a completed scan. +2. Open the **Results** tab. +3. Select the **Classification Breakdown** view. + +The breakdown displays a summary of matches grouped by each applicable compliance framework. + +## Framework Summary + +| Column | Description | +| --- | --- | +| **Framework** | The compliance standard (GDPR, CCPA, HIPAA, PCI DSS, GLBA, CMMC) | +| **Total Matches** | Aggregate count of sensitive data matches mapped to this framework | +| **Files Affected** | Number of distinct files containing matches for this framework | +| **Top Patterns** | The most frequently triggered detection patterns within the framework | + +## Interpreting Results + +- A file may appear under multiple frameworks if its contents match classification rules mapped to different taxonomy groups. +- The **Top Patterns** column highlights which data types contribute the most matches, helping you identify the most common exposure areas. +- Use the breakdown to generate framework-specific remediation plans by focusing on the frameworks with the highest match counts. + +:::note +Classification breakdown results depend on the [taxonomy groups](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/taxonomygroups) and [classification rules](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/classificationrules) configured at the time of the scan. Update your taxonomy mappings and re-scan to reflect new compliance requirements. +::: + +## Next Steps + +- [Export findings](/docs/accessanalyzer/1_0/dashboards/metabase/exportingdata) for compliance reporting +- [View dashboards](/docs/accessanalyzer/1_0/dashboards/overview) for a high-level risk summary diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/matchcounts.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/matchcounts.md new file mode 100644 index 0000000000..2dd3d19f26 --- /dev/null +++ b/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/matchcounts.md @@ -0,0 +1,46 @@ +--- +title: "Match Counts and Locations" +description: "Viewing match counts per file and location details" +sidebar_position: 10 +--- + +# Match Counts and Locations + +After a sensitive data scan completes, the results view displays match counts that summarize how many sensitive data instances were detected, organized by file, pattern, and compliance framework. + +## Understanding Match Counts + +Match counts are reported at three levels: + +| Level | Description | +| --- | --- | +| **Per File** | Total number of sensitive data matches found in each scanned file | +| **Per Pattern** | Number of matches attributed to each detection pattern (for example, SSN, credit card number) | +| **Per Framework** | Aggregate match count grouped by compliance framework (GDPR, HIPAA, PCI DSS, and others) | + +## Viewing Match Details + +To review match counts for a completed scan: + +1. Navigate to the **Scans** section and select the completed scan. +2. Open the **Results** tab to view the summary. +3. Use the **Files** view to see match counts per file, sorted by the number of matches in descending order. +4. Click on a specific file to view the individual pattern matches detected within it. +5. Use the **Patterns** view to see total matches per detection pattern across all scanned files. + +:::note +Match counts reflect the number of pattern matches, not the number of unique sensitive data values. A single file containing the same SSN in multiple locations is counted as multiple matches. +::: + +## Filtering Results + +Use the filter controls to narrow results by: + +- **Data type** — PII, Credentials, PHI, or Financial Records +- **Pattern group** — Filter by a specific pattern group applied during the scan +- **Severity** — Focus on high-priority findings + +## Next Steps + +- [View classification breakdowns](/docs/accessanalyzer/1_0/sensitivedatadiscovery/reviewingresults/classificationbreakdown) to analyze results by compliance framework +- [Access dashboards](/docs/accessanalyzer/1_0/dashboards/overview) for a visual summary of findings diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/runningscan.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/runningscan.md new file mode 100644 index 0000000000..78306fe3bc --- /dev/null +++ b/docs/accessanalyzer/1.0/sensitivedatadiscovery/runningscan.md @@ -0,0 +1,43 @@ +--- +title: "Running a Sensitive Data Scan" +description: "Executing a sensitive data scan and monitoring progress" +sidebar_position: 40 +--- + +# Running a Sensitive Data Scan + +Sensitive data scans analyze files across your connected data sources to detect content matching your configured detection patterns. Scans are configured and launched through the scan creation wizard. + +## Prerequisites + +Before running a sensitive data scan, ensure the following are in place: + +- At least one data source is connected and accessible +- Detection [patterns](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/builtinpatterns) or [pattern groups](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/patterngroups) are configured +- [Taxonomy groups](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/taxonomygroups) and [classification rules](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/classificationrules) are defined for compliance mapping + +## Launching a Scan + +1. Navigate to the **Scans** section in Access Analyzer. +2. Click **Create Scan** to open the scan creation wizard. +3. Select the target **Data Source(s)** to scan. +4. Under **Scan Options**, enable **Sensitive Data Discovery**. +5. Choose the **Pattern Groups** to apply during the scan. +6. Review the scan configuration summary and click **Start Scan**. + +## Monitoring Progress + +Once a scan is running, you can monitor its status from the **Scans** page. The scan detail view displays: + +- **Progress** — Percentage of files processed +- **Files Scanned** — Count of files analyzed so far +- **Matches Found** — Running total of sensitive data matches + +:::warning +Sensitive data scans are resource-intensive. The `sensitive-data-scan` and `data-classification` serverless functions handle detection workloads. Schedule large scans during off-peak hours to minimize impact on system performance. +::: + +## Next Steps + +- [Review match counts](/docs/accessanalyzer/1_0/sensitivedatadiscovery/reviewingresults/matchcounts) after the scan completes +- [Analyze classification breakdowns](/docs/accessanalyzer/1_0/sensitivedatadiscovery/reviewingresults/classificationbreakdown) by compliance framework diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/_category_.json b/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/_category_.json new file mode 100644 index 0000000000..ce0fe0e2ed --- /dev/null +++ b/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Taxonomy and Classification", + "position": 30, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "taxonomygroups" + } +} diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/autovscustom.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/autovscustom.md new file mode 100644 index 0000000000..0f6c9de35d --- /dev/null +++ b/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/autovscustom.md @@ -0,0 +1,41 @@ +--- +title: "Auto vs Custom Classification" +description: "Automatic and custom classification methods" +sidebar_position: 30 +--- + +# Auto vs Custom Classification + +Netwrix Access Analyzer supports two classification approaches for sensitive data: automatic (built-in) classification and custom classification. You can use either method independently or combine them for comprehensive coverage. + +## Automatic Classification + +Automatic classification uses the built-in patterns and taxonomy groups that ship with Access Analyzer. This approach requires no upfront configuration and covers common sensitive data categories out of the box. + +**Advantages:** + +- Ready to use immediately after installation +- Covers standard compliance frameworks (GDPR, CCPA, HIPAA, PCI DSS, GLBA, CMMC) +- Maintained and updated by Netwrix through the Data Classification SDK + +**Best for:** Organizations that need quick time-to-value and standard regulatory coverage. + +## Custom Classification + +Custom classification uses organization-defined regex patterns, pattern groups, and taxonomy mappings. This approach provides full control over what data is detected and how it is categorized. + +**Advantages:** + +- Detects proprietary or non-standard data formats +- Maps findings to internal policies beyond standard frameworks +- Supports region-specific or industry-specific identifiers + +**Best for:** Organizations with unique data formats or compliance requirements not covered by built-in rules. + +## Combining Both Approaches + +For most deployments, a hybrid approach provides the best coverage. Use automatic classification as a baseline, then layer custom patterns for organization-specific needs. + +:::note +Custom rules take precedence over automatic rules when both match the same data and the custom rule has a higher priority. See [Classification Rules](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/classificationrules) for details on priority settings. +::: diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/classificationrules.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/classificationrules.md new file mode 100644 index 0000000000..028e7e4ed0 --- /dev/null +++ b/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/classificationrules.md @@ -0,0 +1,40 @@ +--- +title: "Classification Rules" +description: "Defining rules that combine patterns and taxonomy" +sidebar_position: 20 +--- + +# Classification Rules + +Classification rules connect detection patterns to taxonomy groups, determining how identified sensitive data is categorized and which compliance frameworks apply to each finding. A rule specifies the conditions under which a pattern match is classified under a particular taxonomy. + +## Rule Components + +Each classification rule consists of: + +| Component | Description | +| --- | --- | +| **Name** | A descriptive label for the rule | +| **Pattern or Pattern Group** | The detection patterns that trigger the rule | +| **Taxonomy Group** | The compliance framework or category the match maps to | +| **Priority** | Determines precedence when multiple rules match the same data | + +## Creating a Classification Rule + +1. Navigate to **Sensitive Data Discovery** > **Taxonomy**. +2. Select the **Classification Rules** tab. +3. Click **Add Rule**. +4. Enter a **Name** for the rule. +5. Select the **Pattern** or **Pattern Group** that triggers this classification. +6. Choose the **Taxonomy Group** the rule maps to (for example, HIPAA, PCI DSS, or a custom group). +7. Set the **Priority** level to control rule precedence. +8. Click **Save**. + +:::note +When a single file matches multiple classification rules, all applicable taxonomy groups are reported. Priority determines which classification is displayed first in summary views. +::: + +## Next Steps + +- [Review built-in versus custom classification](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/autovscustom) to decide which approach fits your needs +- [Run a scan](/docs/accessanalyzer/1_0/sensitivedatadiscovery/runningscan) to apply your classification rules against live data diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/taxonomygroups.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/taxonomygroups.md new file mode 100644 index 0000000000..54e9e01635 --- /dev/null +++ b/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/taxonomygroups.md @@ -0,0 +1,42 @@ +--- +title: "Taxonomy Groups" +description: "Creating and managing data classification categories" +sidebar_position: 10 +--- + +# Taxonomy Groups + +Taxonomy groups map classification rules to compliance frameworks, enabling you to align sensitive data findings with regulatory and organizational requirements. Each taxonomy group represents a compliance standard or internal policy against which scan results are evaluated. + +## Supported Compliance Frameworks + +Access Analyzer includes built-in taxonomy groups for the following frameworks: + +| Framework | Description | +| --- | --- | +| GDPR | General Data Protection Regulation — EU personal data protection | +| CCPA | California Consumer Privacy Act — California resident data rights | +| HIPAA | Health Insurance Portability and Accountability Act — protected health information | +| PCI DSS | Payment Card Industry Data Security Standard — cardholder data protection | +| GLBA | Gramm-Leach-Bliley Act — financial institution consumer data | +| CMMC | Cybersecurity Maturity Model Certification — defense contractor requirements | + +## Managing Taxonomy Groups + +To create or modify a taxonomy group: + +1. Navigate to **Sensitive Data Discovery** > **Taxonomy**. +2. Select the **Taxonomy Groups** tab. +3. Click **Add Group** to create a new group, or select an existing group to edit. +4. Provide a **Name** and select the target **Compliance Framework**. +5. Associate [classification rules](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/classificationrules) that define which data types fall under this group. +6. Click **Save**. + +:::note +Built-in taxonomy groups are pre-mapped to their respective frameworks. You can create additional groups for internal policies or regional regulations not covered by the defaults. +::: + +## Next Steps + +- [Define classification rules](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/classificationrules) to control how data is categorized within each taxonomy group +- [Compare built-in and custom classification](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/autovscustom) approaches diff --git a/docs/accessanalyzer/1.0/troubleshooting/_category_.json b/docs/accessanalyzer/1.0/troubleshooting/_category_.json new file mode 100644 index 0000000000..53df54fda4 --- /dev/null +++ b/docs/accessanalyzer/1.0/troubleshooting/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Monitoring and Troubleshooting", + "position": 100, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/troubleshooting/commonissues/_category_.json b/docs/accessanalyzer/1.0/troubleshooting/commonissues/_category_.json new file mode 100644 index 0000000000..feba67eef4 --- /dev/null +++ b/docs/accessanalyzer/1.0/troubleshooting/commonissues/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Common Issues", + "position": 40, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "connectionfailures" + } +} diff --git a/docs/accessanalyzer/1.0/troubleshooting/commonissues/connectionfailures.md b/docs/accessanalyzer/1.0/troubleshooting/commonissues/connectionfailures.md new file mode 100644 index 0000000000..f13e0f0872 --- /dev/null +++ b/docs/accessanalyzer/1.0/troubleshooting/commonissues/connectionfailures.md @@ -0,0 +1,61 @@ +--- +title: "Connection Failures" +description: "Diagnosing and resolving connector connection issues" +sidebar_position: 10 +--- + +# Connection Failures + +Access Analyzer connects to external data sources using protocols such as SMB, LDAP, and Microsoft Graph API. Connection failures prevent scans from running and must be resolved before data collection can proceed. + +## Diagnostic Steps + +1. **Check the connector-api pod status:** + +```bash +kubectl get pods -n access-analyzer -l app=connector-api +kubectl logs -n access-analyzer deploy/connector-api --tail=100 +``` + +2. **Verify network connectivity** from the connector pod to the target: + +```bash +kubectl exec -n access-analyzer deploy/connector-api -- curl -v https://: +``` + +3. **Review the source configuration** in the Access Analyzer web UI. Confirm that the hostname, port, and credentials are correct. + +## SMB Connection Failures + +- Verify that TCP port **445** is open between the Access Analyzer cluster and the target file server. +- Confirm that the service account has the required share and NTFS permissions. +- Check for DNS resolution issues by running `nslookup ` from within the connector pod. + +## LDAP Connection Failures + +- Verify that TCP port **389** (LDAP) or **636** (LDAPS) is reachable. +- Confirm that the bind DN and password are correct. +- For LDAPS, ensure the target server's TLS certificate is trusted. Self-signed certificates may require adding a CA bundle. + +## Microsoft Graph API Failures + +- Confirm that the Azure AD application registration has the required API permissions. +- Verify that the client ID, client secret, and tenant ID are correct and that the secret has not expired. +- Check outbound HTTPS connectivity to `https://graph.microsoft.com` and `https://login.microsoftonline.com`. + +```bash +kubectl exec -n access-analyzer deploy/connector-api -- curl -s -o /dev/null -w "%{http_code}" https://graph.microsoft.com/v1.0/ +``` + +## General Troubleshooting + +| Symptom | Likely Cause | Action | +| --- | --- | --- | +| Connection timeout | Firewall or network policy blocking traffic | Verify firewall rules and Kubernetes network policies | +| Authentication error | Invalid or expired credentials | Update credentials in the source configuration | +| TLS handshake failure | Certificate mismatch or expired certificate | Verify TLS certificates on the target service | +| DNS resolution failure | Incorrect hostname or missing DNS entry | Test DNS from within the connector pod | + +:::note +Connection tests run from the `connector-api` pod. Network access from your local machine does not guarantee access from within the cluster. +::: diff --git a/docs/accessanalyzer/1.0/troubleshooting/commonissues/databaseconnectivity.md b/docs/accessanalyzer/1.0/troubleshooting/commonissues/databaseconnectivity.md new file mode 100644 index 0000000000..fb2aebe74c --- /dev/null +++ b/docs/accessanalyzer/1.0/troubleshooting/commonissues/databaseconnectivity.md @@ -0,0 +1,97 @@ +--- +title: "Database Connectivity" +description: "Resolving PostgreSQL, ClickHouse, and Redis connectivity issues" +sidebar_position: 30 +--- + +# Database Connectivity + +Access Analyzer relies on three backing data stores: PostgreSQL for relational data, ClickHouse for analytics and trace storage, and Redis for sessions, caching, and job queues. Connectivity failures to any of these services impact application functionality. + +## Checking Pod Status + +**Verify that all database pods are running:** + +```bash +kubectl get pods -n access-analyzer -l app=postgresql +kubectl get pods -n access-analyzer -l app=clickhouse +kubectl get pods -n access-analyzer -l app=redis +``` + +A pod not in `Running` status requires immediate attention. Use `kubectl describe pod -n access-analyzer` to inspect events and error details. + +## PostgreSQL + +PostgreSQL stores core application data including user accounts, source configurations, and scan results. + +**Test connectivity from the core-api pod:** + +```bash +kubectl exec -n access-analyzer deploy/core-api -- pg_isready -h postgresql -p 5432 +``` + +**Check active connections:** + +```bash +kubectl exec -n access-analyzer deploy/postgresql -- psql -U postgres -c "SELECT count(*) FROM pg_stat_activity;" +``` + +Common issues: +- **Too many connections** -- The connection pool is exhausted. Restart the application pods or increase the pool size. +- **Pod in CrashLoopBackOff** -- Check PostgreSQL logs for disk space or corruption errors. + +## ClickHouse + +ClickHouse stores analytics data and OpenTelemetry traces in the `access_analyzer_logs` database. + +**Test connectivity:** + +```bash +kubectl exec -n access-analyzer deploy/clickhouse -- clickhouse-client --query "SELECT 1" +``` + +**Check database availability:** + +```bash +kubectl exec -n access-analyzer deploy/clickhouse -- clickhouse-client --query "SHOW DATABASES" +``` + +Common issues: +- **Disk pressure** -- ClickHouse can consume significant storage for trace and analytics data. Monitor disk usage with `kubectl exec -n access-analyzer deploy/clickhouse -- df -h`. +- **Query timeout** -- Large analytical queries can time out. Check ClickHouse server logs for slow query warnings. + +## Redis + +Redis provides session storage, caching, and serves as the job queue backend for Sidekiq. + +**Test connectivity:** + +```bash +kubectl exec -n access-analyzer deploy/redis -- redis-cli ping +``` + +A successful response returns `PONG`. + +**Check memory usage:** + +```bash +kubectl exec -n access-analyzer deploy/redis -- redis-cli info memory | grep used_memory_human +``` + +Common issues: +- **MaxMemory reached** -- Redis evicts keys or rejects writes when memory is full. Increase the memory limit or review eviction policies. +- **Connection refused** -- The Redis pod may have restarted. Check pod status and events. + +## Deep Health Check + +Use the application health endpoint to validate connectivity to all backing services at once: + +```bash +kubectl exec -n access-analyzer deploy/core-api -- curl -s http://localhost:3000/api/v1/monitoring/__health +``` + +This endpoint reports the status of each backing service and identifies which connection is failing. See [Service Health Endpoints](/docs/accessanalyzer/1.0/troubleshooting/healthchecks/endpoints) for more details. + +:::warning +Database connectivity failures cascade across the application. If multiple services report errors simultaneously, start by verifying database pod health before troubleshooting individual application pods. +::: diff --git a/docs/accessanalyzer/1.0/troubleshooting/commonissues/scanerrors.md b/docs/accessanalyzer/1.0/troubleshooting/commonissues/scanerrors.md new file mode 100644 index 0000000000..4bd3cf333c --- /dev/null +++ b/docs/accessanalyzer/1.0/troubleshooting/commonissues/scanerrors.md @@ -0,0 +1,61 @@ +--- +title: "Scan Errors" +description: "Common scan execution errors and solutions" +sidebar_position: 20 +--- + +# Scan Errors + +Scan errors occur when Access Analyzer encounters problems during data collection from configured sources. This page covers common scan errors, their causes, and resolution steps. + +## Checking Scan Status + +Review scan status in the Access Analyzer web UI or check the logs from the relevant pods: + +```bash +kubectl logs -n access-analyzer deploy/core-api --tail=200 | grep -i scan +kubectl logs -n access-analyzer deploy/connector-api --tail=200 | grep -i scan +``` + +## Common Scan Errors + +### Scan Timeout + +Scans that exceed the configured timeout are terminated automatically. + +- **Cause**: Large data sources, slow network connectivity, or insufficient worker resources. +- **Resolution**: Increase the scan timeout if appropriate, reduce the scan scope, or allocate additional resources to worker pods. + +### Pod Failures During Scan + +If the pod executing a scan is killed or restarted mid-scan, the scan fails without completing. + +```bash +kubectl get pods -n access-analyzer --field-selector=status.phase=Failed +kubectl describe pod -n access-analyzer +``` + +- **Cause**: OOMKilled (out of memory), node eviction, or liveness probe timeout. +- **Resolution**: Check pod events for `OOMKilled` status. Increase memory limits for the affected pod if needed. Review node resource pressure with `kubectl top nodes`. + +### Permission Denied Errors + +The scan account lacks the required permissions on the target data source. + +- **Cause**: Insufficient privileges for the configured service account. +- **Resolution**: Verify that the service account has the permissions documented for the source type. See [Connection Failures](/docs/accessanalyzer/1.0/troubleshooting/commonissues/connectionfailures) for protocol-specific requirements. + +### Partial Scan Results + +A scan completes but returns fewer results than expected. + +- **Cause**: Access denied on a subset of resources, or rate limiting by the target API. +- **Resolution**: Review the scan logs for warnings about skipped resources. For API-based sources, check for throttling responses (HTTP 429). + +## Reviewing Scan Job History + +Failed scan jobs appear in the Sidekiq **Retries** or **Dead** tab. See [Failed Job Troubleshooting](/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/failedjobs) for instructions on inspecting and retrying failed jobs. + +:::warning +If scans fail consistently across multiple sources, check cluster-wide resource availability and backing service health before investigating individual source configurations. +::: diff --git a/docs/accessanalyzer/1.0/troubleshooting/healthchecks/_category_.json b/docs/accessanalyzer/1.0/troubleshooting/healthchecks/_category_.json new file mode 100644 index 0000000000..affcb1f52d --- /dev/null +++ b/docs/accessanalyzer/1.0/troubleshooting/healthchecks/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Health Checks", + "position": 10, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "probes" + } +} diff --git a/docs/accessanalyzer/1.0/troubleshooting/healthchecks/endpoints.md b/docs/accessanalyzer/1.0/troubleshooting/healthchecks/endpoints.md new file mode 100644 index 0000000000..772ef5edf7 --- /dev/null +++ b/docs/accessanalyzer/1.0/troubleshooting/healthchecks/endpoints.md @@ -0,0 +1,49 @@ +--- +title: "Service Health Endpoints" +description: "Service-specific health check URLs" +sidebar_position: 20 +--- + +# Service Health Endpoints + +Access Analyzer exposes several HTTP health check endpoints that report on service availability. Use these endpoints to verify that application services are running and responsive. + +## Available Endpoints + +| Endpoint | Purpose | Expected Response | +| --- | --- | --- | +| `/health/live` | Liveness check. Confirms the process is running. | `200 OK` | +| `/health/ready` | Readiness check. Confirms the service can handle requests. | `200 OK` | +| `/api/v1/monitoring/__health` | Deep health check. Validates connectivity to backing services (database, cache). | `200 OK` with JSON status | + +## Querying Health Endpoints + +**From within the cluster, use `kubectl exec` to curl a health endpoint:** + +```bash +kubectl exec -n access-analyzer deploy/core-api -- curl -s http://localhost:3000/health/live +``` + +**Check the readiness endpoint:** + +```bash +kubectl exec -n access-analyzer deploy/core-api -- curl -s http://localhost:3000/health/ready +``` + +**Run the deep health check to verify backing service connectivity:** + +```bash +kubectl exec -n access-analyzer deploy/core-api -- curl -s http://localhost:3000/api/v1/monitoring/__health +``` + +The deep health check at `/api/v1/monitoring/__health` validates that the application can reach PostgreSQL, ClickHouse, and Redis. A failure response from this endpoint identifies which backing service is unreachable. + +## Interpreting Results + +- A `200 OK` response indicates the service is healthy. +- A non-200 response or connection timeout indicates a problem. Check the pod logs for additional context. +- If `/health/live` passes but `/health/ready` fails, the service is running but cannot process requests, typically due to a dependency being unavailable. + +:::note +The `/api/v1/monitoring/__health` endpoint performs active checks against all backing services. Use it for thorough health verification, but avoid calling it at high frequency as it places load on downstream systems. +::: diff --git a/docs/accessanalyzer/1.0/troubleshooting/healthchecks/probes.md b/docs/accessanalyzer/1.0/troubleshooting/healthchecks/probes.md new file mode 100644 index 0000000000..8f2b0697b8 --- /dev/null +++ b/docs/accessanalyzer/1.0/troubleshooting/healthchecks/probes.md @@ -0,0 +1,55 @@ +--- +title: "Liveness and Readiness Probes" +description: "Kubernetes health probe endpoints" +sidebar_position: 10 +--- + +# Liveness and Readiness Probes + +Kubernetes uses liveness and readiness probes to monitor the health of pods in the Access Analyzer deployment. Understanding these probes helps you diagnose pod restarts and service availability issues. + +## How Probes Work + +- **Liveness probes** determine whether a container is running. If a liveness probe fails, Kubernetes restarts the container. +- **Readiness probes** determine whether a container is ready to accept traffic. If a readiness probe fails, Kubernetes removes the pod from service endpoints until it passes again. + +## Checking Probe Status + +**View the current state of all pods in the Access Analyzer namespace:** + +```bash +kubectl get pods -n access-analyzer +``` + +A pod in `CrashLoopBackOff` status typically indicates repeated liveness probe failures. A pod showing `0/1 Ready` may be failing its readiness probe. + +**Inspect probe configuration and recent events for a specific pod:** + +```bash +kubectl describe pod -n access-analyzer +``` + +Look for the `Liveness` and `Readiness` fields in the output to see the probe endpoint, interval, timeout, and failure threshold. The **Events** section at the bottom shows recent probe failures and container restarts. + +**View logs from a pod that is restarting:** + +```bash +kubectl logs -n access-analyzer --previous +``` + +The `--previous` flag retrieves logs from the last terminated container, which is useful when a pod has already restarted. + +## Key Pods to Monitor + +| Pod | Purpose | +| --- | --- | +| `core-api` | Primary API server | +| `webapp` | Web application frontend | +| `connector-api` | Source connector service | +| `postgresql` | Relational data store | +| `clickhouse` | Analytics data store | +| `redis` | Session and cache store | + +:::warning +Frequent pod restarts caused by probe failures often indicate resource pressure (memory or CPU) rather than application bugs. Check node resource utilization with `kubectl top nodes` before investigating application-level issues. +::: diff --git a/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/_category_.json b/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/_category_.json new file mode 100644 index 0000000000..53ae508120 --- /dev/null +++ b/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Background Job Monitoring", + "position": 30, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "sidekiq" + } +} diff --git a/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/failedjobs.md b/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/failedjobs.md new file mode 100644 index 0000000000..b6749b9aa9 --- /dev/null +++ b/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/failedjobs.md @@ -0,0 +1,58 @@ +--- +title: "Failed Job Troubleshooting" +description: "Diagnosing and resolving failed background jobs" +sidebar_position: 30 +--- + +# Failed Job Troubleshooting + +When a Sidekiq background job encounters an error, it enters the retry cycle. Jobs that exhaust all retry attempts move to the dead set. This page explains how to find, diagnose, and resolve failed jobs. + +## Finding Failed Jobs + +Open the [Sidekiq Dashboard](/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/sidekiq) and navigate to the following tabs: + +- **Retries** -- Jobs that failed and are awaiting automatic retry. Each entry displays the error class, error message, and the number of retries attempted. +- **Dead** -- Jobs that exhausted all retry attempts. Dead jobs are not retried automatically and require manual action. + +## Retry Behavior + +Sidekiq uses an exponential backoff strategy for retries. The delay between retries increases with each attempt, following the formula: + +``` +(retry_count ^ 4) + 15 + (random(10) * (retry_count + 1)) seconds +``` + +By default, a job retries up to 25 times before being moved to the dead set. This means a failing job may continue retrying for approximately 21 days before it is considered dead. + +## Diagnosing Failures + +1. **Check the error message** in the Retries or Dead tab. The error class and message typically indicate the root cause (for example, a connection timeout or validation error). +2. **Review application logs** for the time of the failure: + +```bash +kubectl logs -n access-analyzer deploy/core-api --since=1h | grep -i error +``` + +3. **Check backing service health** -- Many job failures stem from database or Redis connectivity issues. See [Database Connectivity](/docs/accessanalyzer/1.0/troubleshooting/commonissues/databaseconnectivity). + +## Handling Dead Jobs + +From the **Dead** tab in the Sidekiq dashboard, you can: + +- **Retry** a specific dead job to re-enqueue it for processing. +- **Delete** a dead job to remove it permanently. +- **Retry All** to re-enqueue all dead jobs at once. + +:::warning +Before retrying dead jobs, ensure the underlying issue has been resolved. Retrying jobs without fixing the root cause will result in repeated failures. +::: + +## Common Failure Causes + +| Cause | Symptoms | Resolution | +| --- | --- | --- | +| Redis unavailable | All jobs fail simultaneously | Verify Redis pod health | +| Database timeout | Jobs in `scans` or `syncs` queues fail | Check PostgreSQL/ClickHouse connectivity | +| External API error | Connector-related jobs fail | Verify source credentials and network access | +| Memory pressure | Jobs killed mid-execution | Increase worker pod memory limits | diff --git a/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/queues.md b/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/queues.md new file mode 100644 index 0000000000..3dc007d084 --- /dev/null +++ b/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/queues.md @@ -0,0 +1,52 @@ +--- +title: "Job Queues and Priorities" +description: "Understanding job queue structure and priority levels" +sidebar_position: 20 +--- + +# Job Queues and Priorities + +Access Analyzer processes background work through seven Sidekiq queues, each serving a specific purpose. Understanding queue roles and priorities helps you identify processing bottlenecks and backpressure. + +## Queue Overview + +| Queue | Priority | Purpose | +| --- | --- | --- | +| `critical` | Highest | System-critical operations that must complete promptly | +| `scans` | High | Data source scan execution | +| `syncs` | High | Data synchronization between sources and the platform | +| `scheduler` | Medium | Periodic task scheduling and orchestration | +| `default` | Medium | General-purpose background work | +| `mailers` | Low | Email notification delivery | +| `low` | Lowest | Deferred or non-urgent tasks | + +Sidekiq workers process queues in priority order. Higher-priority queues are drained before lower-priority ones. + +## Monitoring Queue Depth + +**From the Sidekiq dashboard**, navigate to the **Queues** tab to view the current size of each queue. A queue size that grows continuously indicates that jobs are being enqueued faster than workers can process them. + +**From the command line, query Prometheus for queue sizes:** + +```bash +kubectl exec -n access-analyzer deploy/prometheus -- \ + promtool query instant http://localhost:9090 'sidekiq_queue_size' +``` + +## Identifying Backpressure + +Backpressure occurs when one or more queues accumulate jobs faster than they are processed. Common causes include: + +- **Resource constraints** -- Insufficient CPU or memory on worker pods. Check with `kubectl top pods -n access-analyzer`. +- **Downstream dependency failures** -- Database or external service unavailability causing job retries and requeuing. +- **Large scan jobs** -- A scan targeting a large data source can consume worker capacity, delaying other queues. + +:::warning +If the `critical` queue has a sustained non-zero depth, investigate immediately. Delayed critical jobs can affect system stability and data consistency. +::: + +## Corrective Actions + +- Scale worker replicas if resource limits allow. +- Investigate and resolve downstream dependency failures (see [Database Connectivity](/docs/accessanalyzer/1.0/troubleshooting/commonissues/databaseconnectivity)). +- Stagger large scan jobs to avoid overwhelming worker capacity. diff --git a/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/sidekiq.md b/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/sidekiq.md new file mode 100644 index 0000000000..a7b43638c9 --- /dev/null +++ b/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/sidekiq.md @@ -0,0 +1,50 @@ +--- +title: "Sidekiq Dashboard" +description: "Monitoring background jobs via the Sidekiq web UI" +sidebar_position: 10 +--- + +# Sidekiq Dashboard + +Access Analyzer uses Sidekiq to process background jobs such as scans, syncs, and scheduled tasks. The Sidekiq web dashboard provides real-time visibility into job processing, queue health, and worker status. + +## Accessing the Dashboard + +The Sidekiq dashboard is available at the `/sidekiq` path on your Access Analyzer instance: + +``` +https:///sidekiq +``` + +The dashboard requires authentication. Enter the configured username and password when prompted. + +:::note +Dashboard credentials are set during installation. Contact your system administrator if you do not have the credentials. +::: + +## Dashboard Capabilities + +The Sidekiq web UI provides the following views: + +- **Dashboard** -- Real-time graph of processed and failed jobs over time. +- **Busy** -- Lists workers currently executing jobs, including the job class and arguments. +- **Queues** -- Displays all queues with their current size. Use this to identify backpressure. +- **Retries** -- Shows jobs that failed and are scheduled for automatic retry. +- **Scheduled** -- Lists jobs enqueued for future execution. +- **Dead** -- Contains jobs that exhausted all retry attempts. These require manual intervention. + +## Checking Job Throughput + +From the dashboard home page, review the **Processed** and **Failed** counters. A healthy system shows a steadily increasing processed count with a low or zero failed count. + +If the failed count is climbing, navigate to the **Retries** tab to inspect the error messages and determine the root cause. + +## Infrastructure Dependency + +Sidekiq depends on Redis for job storage and queue management. If the Sidekiq dashboard is unreachable or shows no data, verify that the Redis pod is running: + +```bash +kubectl get pods -n access-analyzer -l app=redis +``` + +See [Job Queues and Priorities](/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/queues) for details on individual queue behavior. diff --git a/docs/accessanalyzer/1.0/troubleshooting/observability/_category_.json b/docs/accessanalyzer/1.0/troubleshooting/observability/_category_.json new file mode 100644 index 0000000000..d6e5ecaf0a --- /dev/null +++ b/docs/accessanalyzer/1.0/troubleshooting/observability/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Observability", + "position": 20, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "opentelemetry" + } +} diff --git a/docs/accessanalyzer/1.0/troubleshooting/observability/opentelemetry.md b/docs/accessanalyzer/1.0/troubleshooting/observability/opentelemetry.md new file mode 100644 index 0000000000..d9d1ec28e6 --- /dev/null +++ b/docs/accessanalyzer/1.0/troubleshooting/observability/opentelemetry.md @@ -0,0 +1,76 @@ +--- +title: "OpenTelemetry Traces and Metrics" +description: "Distributed tracing and metric collection" +sidebar_position: 10 +--- + +# OpenTelemetry Traces and Metrics + +Access Analyzer uses OpenTelemetry (OTel) for distributed tracing. Traces are collected by the `otel-collector` pod and stored in ClickHouse, allowing you to analyze request flows and identify performance bottlenecks. + +## Architecture + +Trace data flows through the following path: + +1. Application services instrument outgoing requests and operations with OTel spans. +2. The `otel-collector` pod receives spans and exports them to ClickHouse. +3. Traces are stored in the `access_analyzer_logs` database in ClickHouse. + +## Querying Traces in ClickHouse + +**Connect to the ClickHouse pod:** + +```bash +kubectl exec -it -n access-analyzer deploy/clickhouse -- clickhouse-client +``` + +**List available tables in the trace database:** + +```bash +USE access_analyzer_logs; +SHOW TABLES; +``` + +**Query recent traces by service name:** + +```bash +SELECT TraceId, SpanName, Duration, StatusCode +FROM otel_traces +WHERE ServiceName = 'core-api' +ORDER BY Timestamp DESC +LIMIT 20; +``` + +**Find slow spans exceeding a duration threshold (in nanoseconds):** + +```bash +SELECT TraceId, SpanName, Duration +FROM otel_traces +WHERE Duration > 5000000000 +ORDER BY Duration DESC +LIMIT 10; +``` + +## Common Trace Analysis + +- **High latency requests** -- Query for spans with long durations to identify slow database queries or external API calls. +- **Error spans** -- Filter by `StatusCode` to find spans that completed with errors. +- **Cross-service tracing** -- Use a `TraceId` to follow a request across `core-api`, `connector-api`, and backing services. + +## Verifying the OTel Collector + +**Check that the collector pod is running:** + +```bash +kubectl get pods -n access-analyzer -l app=otel-collector +``` + +**View collector logs for export errors:** + +```bash +kubectl logs -n access-analyzer deploy/otel-collector --tail=50 +``` + +:::note +Trace retention depends on your ClickHouse storage configuration. Monitor disk usage on the ClickHouse pod to ensure traces are not consuming excessive storage. +::: diff --git a/docs/accessanalyzer/1.0/troubleshooting/observability/prometheus.md b/docs/accessanalyzer/1.0/troubleshooting/observability/prometheus.md new file mode 100644 index 0000000000..253f2f8b3a --- /dev/null +++ b/docs/accessanalyzer/1.0/troubleshooting/observability/prometheus.md @@ -0,0 +1,70 @@ +--- +title: "Prometheus Monitoring" +description: "Prometheus metrics and alerting" +sidebar_position: 20 +--- + +# Prometheus Monitoring + +Access Analyzer includes a Prometheus instance that collects metrics from application services and infrastructure components. Use Prometheus to monitor resource utilization, request rates, and application performance. + +## Accessing Prometheus + +The Prometheus pod runs in the `access-analyzer` namespace. To access the Prometheus web UI, set up a port forward: + +```bash +kubectl port-forward -n access-analyzer deploy/prometheus 9090:9090 +``` + +Then open `http://localhost:9090` in your browser. + +## Key Metrics to Monitor + +| Metric | Description | +| --- | --- | +| `container_memory_usage_bytes` | Memory consumption per container | +| `container_cpu_usage_seconds_total` | CPU usage per container | +| `http_request_duration_seconds` | Request latency histogram | +| `http_requests_total` | Total request count by status code | +| `sidekiq_queue_size` | Number of jobs waiting in each Sidekiq queue | +| `pg_stat_activity_count` | Active PostgreSQL connections | + +## Useful PromQL Queries + +**Check memory usage for Access Analyzer pods:** + +```bash +container_memory_usage_bytes{namespace="access-analyzer"} +``` + +**Calculate request error rate over the last 5 minutes:** + +```bash +rate(http_requests_total{namespace="access-analyzer", status=~"5.."}[5m]) +``` + +**Monitor Sidekiq queue depth:** + +```bash +sidekiq_queue_size{namespace="access-analyzer"} +``` + +## Recording Rules + +Access Analyzer ships with Prometheus recording rules that pre-compute frequently used metric aggregations. Recording rules reduce query latency for dashboards and alerts. View the active recording rules in the Prometheus UI under **Status > Rules**. + +## Verifying Prometheus Health + +**Confirm the Prometheus pod is running:** + +```bash +kubectl get pods -n access-analyzer -l app=prometheus +``` + +**Check Prometheus targets to ensure all scrape endpoints are reachable:** + +Open `http://localhost:9090/targets` (with port forward active) and verify all targets show an **UP** state. + +:::warning +If Prometheus targets appear as **DOWN**, verify that the target pods are running and that network policies allow traffic from the Prometheus pod on the metrics port. +::: diff --git a/docs/accessanalyzer/1.0/troubleshooting/overview.md b/docs/accessanalyzer/1.0/troubleshooting/overview.md new file mode 100644 index 0000000000..806ed1a446 --- /dev/null +++ b/docs/accessanalyzer/1.0/troubleshooting/overview.md @@ -0,0 +1,70 @@ +--- +title: "Monitoring and Troubleshooting" +description: "Health checks, observability, and common issue resolution" +sidebar_position: 1 +--- + +# Monitoring and Troubleshooting + +This section provides guidance for monitoring the health of your Netwrix Access Analyzer deployment and resolving common issues. Use the categories below to navigate to the relevant topic. + +## Troubleshooting Categories + +| Category | Description | Link | +| --- | --- | --- | +| Health Checks | Kubernetes probes and service health endpoints | [Probes](/docs/accessanalyzer/1.0/troubleshooting/healthchecks/probes), [Endpoints](/docs/accessanalyzer/1.0/troubleshooting/healthchecks/endpoints) | +| Observability | Distributed tracing and metrics collection | [OpenTelemetry](/docs/accessanalyzer/1.0/troubleshooting/observability/opentelemetry), [Prometheus](/docs/accessanalyzer/1.0/troubleshooting/observability/prometheus) | +| Job Monitoring | Background job processing and queue health | [Sidekiq](/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/sidekiq), [Queues](/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/queues), [Failed Jobs](/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/failedjobs) | +| Common Issues | Connection failures, scan errors, and database connectivity | [Connections](/docs/accessanalyzer/1.0/troubleshooting/commonissues/connectionfailures), [Scans](/docs/accessanalyzer/1.0/troubleshooting/commonissues/scanerrors), [Database](/docs/accessanalyzer/1.0/troubleshooting/commonissues/databaseconnectivity) | + +## Quick Diagnostic Commands + +Run the following commands to get an immediate overview of system health. + +**Check all pod status across namespaces:** + +```bash +kubectl get pods -A +``` + +**View resource consumption for nodes and pods:** + +```bash +kubectl top nodes +kubectl top pods -n access-analyzer +``` + +**Check ArgoCD application sync status:** + +```bash +kubectl get apps -n argocd +``` + +**View logs for a specific pod:** + +```bash +kubectl logs -n access-analyzer --tail=100 +``` + +**Review installer and preflight logs:** + +```bash +cat /var/log/dspm-installer.log +cat /var/log/dspm-preflight.json +``` + +## Installer Exit Codes + +If installation failed, check the exit code to identify the failure category. + +| Exit Code | Meaning | +| --- | --- | +| 10 | License validation failure | +| 50 | K3s installation or startup failure | +| 60 | ArgoCD deployment failure | +| 70 | Application readiness timeout | +| 80 | Preflight check failure (CPU, memory, disk, kernel, or cgroups) | + +:::note +Most troubleshooting commands require `kubectl` access to the cluster. Ensure your kubeconfig is configured correctly before running diagnostics. +::: diff --git a/kb_allowlist.json b/kb_allowlist.json index 0ce970bb8f..356ff9e772 100644 --- a/kb_allowlist.json +++ b/kb_allowlist.json @@ -3,6 +3,7 @@ "current" ], "accessanalyzer": [ + "1.0", "11.6", "12.0" ], diff --git a/sidebars/accessanalyzer/1.0.js b/sidebars/accessanalyzer/1.0.js new file mode 100644 index 0000000000..f4e8941a40 --- /dev/null +++ b/sidebars/accessanalyzer/1.0.js @@ -0,0 +1,8 @@ +module.exports = { + sidebar: [ + { + type: 'autogenerated', + dirName: '.', + }, + ], +}; diff --git a/src/config/products.js b/src/config/products.js index ec129b0766..730b361205 100644 --- a/src/config/products.js +++ b/src/config/products.js @@ -60,6 +60,12 @@ export const PRODUCTS = [ categories: ['Data Security Posture Management (DSPM)', 'Identity Threat Detection & Response (ITDR)'], icon: '', versions: [ + { + version: '1.0', + label: '1.0', + isLatest: false, + sidebarFile: './sidebars/accessanalyzer/1.0.js', + }, { version: '12.0', label: '12.0', From 5dc5bb73acc60fa5b5d3982431bd2ab4cf6e53cd Mon Sep 17 00:00:00 2001 From: carlos-mejia_nwx Date: Thu, 19 Mar 2026 21:36:21 -0400 Subject: [PATCH 02/62] =?UTF-8?q?AA26:=20Restructure=20outline=20=E2=80=94?= =?UTF-8?q?=20Overview=20+=20KB=20only,=20on-prem=20verbiage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Move requirements/ and install/ under overview/ as subsections - Rename overview intro to "Intro to the Product" - Delete architecture.md (not needed) - Remove 7 top-level sections: getting started, connectors, admin, dashboards, sensitive data discovery, activity monitoring, troubleshooting - Clear KB articles, keep as placeholder - Update all verbiage to reflect on-premises deployment (not cloud/SaaS) Co-Authored-By: Claude Opus 4.6 --- .../1.0/activitymonitoring/_category_.json | 10 -- .../configuration/_category_.json | 10 -- .../configuration/batchprocessing.md | 8 -- .../configuration/connectingnam.md | 8 -- .../configuration/enablingsyslog.md | 8 -- .../1.0/activitymonitoring/overview.md | 8 -- .../viewingdata/_category_.json | 10 -- .../viewingdata/fileaccessevents.md | 8 -- .../viewingdata/useractivitypatterns.md | 8 -- docs/accessanalyzer/1.0/admin/_category_.json | 10 -- .../1.0/admin/auditlogs/_category_.json | 10 -- .../1.0/admin/auditlogs/export.md | 43 -------- .../1.0/admin/auditlogs/overview.md | 39 -------- .../1.0/admin/authentication/_category_.json | 10 -- .../1.0/admin/authentication/overview.md | 34 ------- .../admin/authentication/sessionmonitoring.md | 38 -------- .../1.0/admin/authentication/tokenrefresh.md | 34 ------- .../1.0/admin/iam/_category_.json | 10 -- .../1.0/admin/iam/identitiesentitlements.md | 36 ------- .../1.0/admin/iam/identitysync.md | 43 -------- docs/accessanalyzer/1.0/admin/iam/overview.md | 32 ------ .../1.0/admin/iam/permissionpaths.md | 39 -------- .../1.0/admin/navigate/_category_.json | 10 -- .../1.0/admin/navigate/datatables.md | 35 ------- .../1.0/admin/navigate/overview.md | 27 ------ .../1.0/admin/navigate/sidebar.md | 34 ------- docs/accessanalyzer/1.0/admin/overview.md | 29 ------ .../1.0/admin/scans/_category_.json | 10 -- .../1.0/admin/scans/executionhistory.md | 44 --------- .../1.0/admin/scans/overview.md | 31 ------ .../1.0/admin/scans/runningstop.md | 42 -------- .../1.0/admin/scans/scantypes.md | 64 ------------ .../1.0/admin/scans/scheduling.md | 50 ---------- .../1.0/admin/sensitivedata/_category_.json | 10 -- .../sensitivedata/customclassification.md | 44 --------- .../1.0/admin/sensitivedata/overview.md | 34 ------- .../1.0/admin/sensitivedata/patterngroups.md | 43 -------- .../1.0/admin/sensitivedata/taxonomygroups.md | 39 -------- .../1.0/admin/serviceaccounts/_category_.json | 10 -- .../1.0/admin/serviceaccounts/associating.md | 42 -------- .../admin/serviceaccounts/credentialtypes.md | 37 ------- .../1.0/admin/serviceaccounts/overview.md | 33 ------- .../1.0/admin/settings/_category_.json | 10 -- .../1.0/admin/settings/featureflags.md | 48 --------- .../1.0/admin/settings/overview.md | 33 ------- .../1.0/admin/settings/scanlimits.md | 37 ------- .../1.0/admin/settings/sessionttl.md | 41 -------- .../1.0/admin/sources/_category_.json | 10 -- .../1.0/admin/sources/editdelete.md | 40 -------- .../1.0/admin/sources/overview.md | 42 -------- .../1.0/admin/sources/sourcegroups.md | 51 ---------- .../1.0/admin/sources/sourcetypes.md | 35 ------- .../1.0/admin/sources/testconnections.md | 54 ----------- docs/accessanalyzer/1.0/admin/systemlogs.md | 47 --------- .../1.0/admin/users/_category_.json | 10 -- .../1.0/admin/users/overview.md | 38 -------- docs/accessanalyzer/1.0/admin/users/roles.md | 36 ------- .../1.0/admin/users/sessions.md | 35 ------- .../1.0/connectors/_category_.json | 10 -- .../1.0/connectors/iam/_category_.json | 10 -- .../iam/activedirectory/_category_.json | 10 -- .../iam/activedirectory/connectionsetup.md | 47 --------- .../iam/activedirectory/customattributes.md | 12 --- .../iam/activedirectory/groupmembership.md | 26 ----- .../iam/activedirectory/usergroupsync.md | 30 ------ .../connectors/iam/entraid/_category_.json | 10 -- .../connectors/iam/entraid/appregistration.md | 74 -------------- .../connectors/iam/entraid/certificateauth.md | 12 --- .../connectors/iam/entraid/usergroupsync.md | 47 --------- .../iam/localgroups/_category_.json | 10 -- .../iam/localgroups/powershellsetup.md | 52 ---------- .../iam/localgroups/usergroupcollection.md | 40 -------- .../1.0/connectors/iam/overview.md | 21 ---- .../accessanalyzer/1.0/connectors/overview.md | 42 -------- .../1.0/connectors/source/_category_.json | 10 -- .../connectors/source/cifs/_category_.json | 10 -- .../source/cifs/connectionconfig.md | 79 --------------- .../source/cifs/filevssharelevel.md | 53 ---------- .../connectors/source/cifs/ntfspermissions.md | 33 ------- .../source/cifs/scandepthworkers.md | 54 ----------- .../source/cifs/shareenumeration.md | 53 ---------- .../1.0/connectors/source/overview.md | 23 ----- .../source/sharepointonline/_category_.json | 10 -- .../sharepointonline/connectionconfig.md | 44 --------- .../permissionsharinglinks.md | 35 ------- .../sharepointonline/scanningspecificsites.md | 30 ------ .../sharepointonline/sitelibraryenum.md | 29 ------ .../1.0/dashboards/_category_.json | 10 -- .../1.0/dashboards/activedirectory.md | 8 -- .../1.0/dashboards/copilotreadiness.md | 8 -- .../1.0/dashboards/datasecurity.md | 8 -- docs/accessanalyzer/1.0/dashboards/entraid.md | 8 -- .../1.0/dashboards/metabase/_category_.json | 10 -- .../dashboards/metabase/accessingreports.md | 36 ------- .../1.0/dashboards/metabase/exportingdata.md | 41 -------- .../1.0/dashboards/metabase/savedreports.md | 38 -------- .../accessanalyzer/1.0/dashboards/overview.md | 33 ------- .../1.0/gettingstarted/_category_.json | 10 -- .../gettingstarted/dashboardwalkthrough.md | 44 --------- .../1.0/gettingstarted/firstlogin.md | 52 ---------- .../gettingstarted/firstscan/_category_.json | 10 -- .../gettingstarted/firstscan/addingsource.md | 70 ------------- .../firstscan/configuringscan.md | 94 ------------------ .../1.0/gettingstarted/firstscan/overview.md | 28 ------ .../gettingstarted/firstscan/runningscan.md | 56 ----------- .../firstscan/viewingresults.md | 49 ---------- .../1.0/gettingstarted/overview.md | 26 ----- docs/accessanalyzer/1.0/index.md | 18 +--- .../1.0/overview/architecture.md | 69 ------------- .../{ => overview}/install/_category_.json | 0 .../1.0/{ => overview}/install/dspmctl.md | 0 .../install/environmentvariables.md | 0 .../1.0/{ => overview}/install/network.md | 0 .../1.0/{ => overview}/install/overview.md | 0 .../1.0/{ => overview}/install/postinstall.md | 0 .../1.0/{ => overview}/install/preflight.md | 0 .../{ => overview}/install/quickinstall.md | 0 .../{ => overview}/install/requirements.md | 0 .../1.0/{ => overview}/install/security.md | 0 .../1.0/{ => overview}/install/ssl.md | 0 .../1.0/{ => overview}/install/stepbystep.md | 0 .../1.0/{ => overview}/install/uninstall.md | 0 .../1.0/{ => overview}/install/upgrade.md | 0 .../1.0/overview/keyconcepts.md | 4 +- docs/accessanalyzer/1.0/overview/overview.md | 18 ++-- .../requirements/_category_.json | 0 .../requirements/connectors/_category_.json | 0 .../connectors/activedirectory.md | 0 .../requirements/connectors/cifs.md | 0 .../requirements/connectors/entraid.md | 0 .../requirements/connectors/localgroups.md | 0 .../connectors/sharepointonline.md | 0 .../requirements/database/_category_.json | 0 .../requirements/database/clickhouse.md | 0 .../requirements/database/postgresql.md | 0 .../requirements/database/redis.md | 0 .../{ => overview}/requirements/overview.md | 0 .../requirements/system/_category_.json | 0 .../requirements/system/hardware.md | 0 .../requirements/system/kubernetes.md | 0 .../requirements/system/network.md | 0 .../sensitivedatadiscovery/_category_.json | 10 -- .../1.0/sensitivedatadiscovery/overview.md | 32 ------ .../patterns/_category_.json | 10 -- .../patterns/builtinpatterns.md | 34 ------- .../patterns/custompatterns.md | 47 --------- .../patterns/patterngroups.md | 39 -------- .../reviewingresults/_category_.json | 10 -- .../classificationbreakdown.md | 43 -------- .../reviewingresults/matchcounts.md | 46 --------- .../1.0/sensitivedatadiscovery/runningscan.md | 43 -------- .../taxonomy/_category_.json | 10 -- .../taxonomy/autovscustom.md | 41 -------- .../taxonomy/classificationrules.md | 40 -------- .../taxonomy/taxonomygroups.md | 42 -------- .../1.0/troubleshooting/_category_.json | 10 -- .../commonissues/_category_.json | 10 -- .../commonissues/connectionfailures.md | 61 ------------ .../commonissues/databaseconnectivity.md | 97 ------------------- .../commonissues/scanerrors.md | 61 ------------ .../healthchecks/_category_.json | 10 -- .../troubleshooting/healthchecks/endpoints.md | 49 ---------- .../troubleshooting/healthchecks/probes.md | 55 ----------- .../jobmonitoring/_category_.json | 10 -- .../jobmonitoring/failedjobs.md | 58 ----------- .../troubleshooting/jobmonitoring/queues.md | 52 ---------- .../troubleshooting/jobmonitoring/sidekiq.md | 50 ---------- .../observability/_category_.json | 10 -- .../observability/opentelemetry.md | 76 --------------- .../observability/prometheus.md | 70 ------------- .../1.0/troubleshooting/overview.md | 70 ------------- 171 files changed, 15 insertions(+), 4536 deletions(-) delete mode 100644 docs/accessanalyzer/1.0/activitymonitoring/_category_.json delete mode 100644 docs/accessanalyzer/1.0/activitymonitoring/configuration/_category_.json delete mode 100644 docs/accessanalyzer/1.0/activitymonitoring/configuration/batchprocessing.md delete mode 100644 docs/accessanalyzer/1.0/activitymonitoring/configuration/connectingnam.md delete mode 100644 docs/accessanalyzer/1.0/activitymonitoring/configuration/enablingsyslog.md delete mode 100644 docs/accessanalyzer/1.0/activitymonitoring/overview.md delete mode 100644 docs/accessanalyzer/1.0/activitymonitoring/viewingdata/_category_.json delete mode 100644 docs/accessanalyzer/1.0/activitymonitoring/viewingdata/fileaccessevents.md delete mode 100644 docs/accessanalyzer/1.0/activitymonitoring/viewingdata/useractivitypatterns.md delete mode 100644 docs/accessanalyzer/1.0/admin/_category_.json delete mode 100644 docs/accessanalyzer/1.0/admin/auditlogs/_category_.json delete mode 100644 docs/accessanalyzer/1.0/admin/auditlogs/export.md delete mode 100644 docs/accessanalyzer/1.0/admin/auditlogs/overview.md delete mode 100644 docs/accessanalyzer/1.0/admin/authentication/_category_.json delete mode 100644 docs/accessanalyzer/1.0/admin/authentication/overview.md delete mode 100644 docs/accessanalyzer/1.0/admin/authentication/sessionmonitoring.md delete mode 100644 docs/accessanalyzer/1.0/admin/authentication/tokenrefresh.md delete mode 100644 docs/accessanalyzer/1.0/admin/iam/_category_.json delete mode 100644 docs/accessanalyzer/1.0/admin/iam/identitiesentitlements.md delete mode 100644 docs/accessanalyzer/1.0/admin/iam/identitysync.md delete mode 100644 docs/accessanalyzer/1.0/admin/iam/overview.md delete mode 100644 docs/accessanalyzer/1.0/admin/iam/permissionpaths.md delete mode 100644 docs/accessanalyzer/1.0/admin/navigate/_category_.json delete mode 100644 docs/accessanalyzer/1.0/admin/navigate/datatables.md delete mode 100644 docs/accessanalyzer/1.0/admin/navigate/overview.md delete mode 100644 docs/accessanalyzer/1.0/admin/navigate/sidebar.md delete mode 100644 docs/accessanalyzer/1.0/admin/overview.md delete mode 100644 docs/accessanalyzer/1.0/admin/scans/_category_.json delete mode 100644 docs/accessanalyzer/1.0/admin/scans/executionhistory.md delete mode 100644 docs/accessanalyzer/1.0/admin/scans/overview.md delete mode 100644 docs/accessanalyzer/1.0/admin/scans/runningstop.md delete mode 100644 docs/accessanalyzer/1.0/admin/scans/scantypes.md delete mode 100644 docs/accessanalyzer/1.0/admin/scans/scheduling.md delete mode 100644 docs/accessanalyzer/1.0/admin/sensitivedata/_category_.json delete mode 100644 docs/accessanalyzer/1.0/admin/sensitivedata/customclassification.md delete mode 100644 docs/accessanalyzer/1.0/admin/sensitivedata/overview.md delete mode 100644 docs/accessanalyzer/1.0/admin/sensitivedata/patterngroups.md delete mode 100644 docs/accessanalyzer/1.0/admin/sensitivedata/taxonomygroups.md delete mode 100644 docs/accessanalyzer/1.0/admin/serviceaccounts/_category_.json delete mode 100644 docs/accessanalyzer/1.0/admin/serviceaccounts/associating.md delete mode 100644 docs/accessanalyzer/1.0/admin/serviceaccounts/credentialtypes.md delete mode 100644 docs/accessanalyzer/1.0/admin/serviceaccounts/overview.md delete mode 100644 docs/accessanalyzer/1.0/admin/settings/_category_.json delete mode 100644 docs/accessanalyzer/1.0/admin/settings/featureflags.md delete mode 100644 docs/accessanalyzer/1.0/admin/settings/overview.md delete mode 100644 docs/accessanalyzer/1.0/admin/settings/scanlimits.md delete mode 100644 docs/accessanalyzer/1.0/admin/settings/sessionttl.md delete mode 100644 docs/accessanalyzer/1.0/admin/sources/_category_.json delete mode 100644 docs/accessanalyzer/1.0/admin/sources/editdelete.md delete mode 100644 docs/accessanalyzer/1.0/admin/sources/overview.md delete mode 100644 docs/accessanalyzer/1.0/admin/sources/sourcegroups.md delete mode 100644 docs/accessanalyzer/1.0/admin/sources/sourcetypes.md delete mode 100644 docs/accessanalyzer/1.0/admin/sources/testconnections.md delete mode 100644 docs/accessanalyzer/1.0/admin/systemlogs.md delete mode 100644 docs/accessanalyzer/1.0/admin/users/_category_.json delete mode 100644 docs/accessanalyzer/1.0/admin/users/overview.md delete mode 100644 docs/accessanalyzer/1.0/admin/users/roles.md delete mode 100644 docs/accessanalyzer/1.0/admin/users/sessions.md delete mode 100644 docs/accessanalyzer/1.0/connectors/_category_.json delete mode 100644 docs/accessanalyzer/1.0/connectors/iam/_category_.json delete mode 100644 docs/accessanalyzer/1.0/connectors/iam/activedirectory/_category_.json delete mode 100644 docs/accessanalyzer/1.0/connectors/iam/activedirectory/connectionsetup.md delete mode 100644 docs/accessanalyzer/1.0/connectors/iam/activedirectory/customattributes.md delete mode 100644 docs/accessanalyzer/1.0/connectors/iam/activedirectory/groupmembership.md delete mode 100644 docs/accessanalyzer/1.0/connectors/iam/activedirectory/usergroupsync.md delete mode 100644 docs/accessanalyzer/1.0/connectors/iam/entraid/_category_.json delete mode 100644 docs/accessanalyzer/1.0/connectors/iam/entraid/appregistration.md delete mode 100644 docs/accessanalyzer/1.0/connectors/iam/entraid/certificateauth.md delete mode 100644 docs/accessanalyzer/1.0/connectors/iam/entraid/usergroupsync.md delete mode 100644 docs/accessanalyzer/1.0/connectors/iam/localgroups/_category_.json delete mode 100644 docs/accessanalyzer/1.0/connectors/iam/localgroups/powershellsetup.md delete mode 100644 docs/accessanalyzer/1.0/connectors/iam/localgroups/usergroupcollection.md delete mode 100644 docs/accessanalyzer/1.0/connectors/iam/overview.md delete mode 100644 docs/accessanalyzer/1.0/connectors/overview.md delete mode 100644 docs/accessanalyzer/1.0/connectors/source/_category_.json delete mode 100644 docs/accessanalyzer/1.0/connectors/source/cifs/_category_.json delete mode 100644 docs/accessanalyzer/1.0/connectors/source/cifs/connectionconfig.md delete mode 100644 docs/accessanalyzer/1.0/connectors/source/cifs/filevssharelevel.md delete mode 100644 docs/accessanalyzer/1.0/connectors/source/cifs/ntfspermissions.md delete mode 100644 docs/accessanalyzer/1.0/connectors/source/cifs/scandepthworkers.md delete mode 100644 docs/accessanalyzer/1.0/connectors/source/cifs/shareenumeration.md delete mode 100644 docs/accessanalyzer/1.0/connectors/source/overview.md delete mode 100644 docs/accessanalyzer/1.0/connectors/source/sharepointonline/_category_.json delete mode 100644 docs/accessanalyzer/1.0/connectors/source/sharepointonline/connectionconfig.md delete mode 100644 docs/accessanalyzer/1.0/connectors/source/sharepointonline/permissionsharinglinks.md delete mode 100644 docs/accessanalyzer/1.0/connectors/source/sharepointonline/scanningspecificsites.md delete mode 100644 docs/accessanalyzer/1.0/connectors/source/sharepointonline/sitelibraryenum.md delete mode 100644 docs/accessanalyzer/1.0/dashboards/_category_.json delete mode 100644 docs/accessanalyzer/1.0/dashboards/activedirectory.md delete mode 100644 docs/accessanalyzer/1.0/dashboards/copilotreadiness.md delete mode 100644 docs/accessanalyzer/1.0/dashboards/datasecurity.md delete mode 100644 docs/accessanalyzer/1.0/dashboards/entraid.md delete mode 100644 docs/accessanalyzer/1.0/dashboards/metabase/_category_.json delete mode 100644 docs/accessanalyzer/1.0/dashboards/metabase/accessingreports.md delete mode 100644 docs/accessanalyzer/1.0/dashboards/metabase/exportingdata.md delete mode 100644 docs/accessanalyzer/1.0/dashboards/metabase/savedreports.md delete mode 100644 docs/accessanalyzer/1.0/dashboards/overview.md delete mode 100644 docs/accessanalyzer/1.0/gettingstarted/_category_.json delete mode 100644 docs/accessanalyzer/1.0/gettingstarted/dashboardwalkthrough.md delete mode 100644 docs/accessanalyzer/1.0/gettingstarted/firstlogin.md delete mode 100644 docs/accessanalyzer/1.0/gettingstarted/firstscan/_category_.json delete mode 100644 docs/accessanalyzer/1.0/gettingstarted/firstscan/addingsource.md delete mode 100644 docs/accessanalyzer/1.0/gettingstarted/firstscan/configuringscan.md delete mode 100644 docs/accessanalyzer/1.0/gettingstarted/firstscan/overview.md delete mode 100644 docs/accessanalyzer/1.0/gettingstarted/firstscan/runningscan.md delete mode 100644 docs/accessanalyzer/1.0/gettingstarted/firstscan/viewingresults.md delete mode 100644 docs/accessanalyzer/1.0/gettingstarted/overview.md delete mode 100644 docs/accessanalyzer/1.0/overview/architecture.md rename docs/accessanalyzer/1.0/{ => overview}/install/_category_.json (100%) rename docs/accessanalyzer/1.0/{ => overview}/install/dspmctl.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/install/environmentvariables.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/install/network.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/install/overview.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/install/postinstall.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/install/preflight.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/install/quickinstall.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/install/requirements.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/install/security.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/install/ssl.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/install/stepbystep.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/install/uninstall.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/install/upgrade.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/requirements/_category_.json (100%) rename docs/accessanalyzer/1.0/{ => overview}/requirements/connectors/_category_.json (100%) rename docs/accessanalyzer/1.0/{ => overview}/requirements/connectors/activedirectory.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/requirements/connectors/cifs.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/requirements/connectors/entraid.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/requirements/connectors/localgroups.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/requirements/connectors/sharepointonline.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/requirements/database/_category_.json (100%) rename docs/accessanalyzer/1.0/{ => overview}/requirements/database/clickhouse.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/requirements/database/postgresql.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/requirements/database/redis.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/requirements/overview.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/requirements/system/_category_.json (100%) rename docs/accessanalyzer/1.0/{ => overview}/requirements/system/hardware.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/requirements/system/kubernetes.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/requirements/system/network.md (100%) delete mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/_category_.json delete mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/overview.md delete mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/_category_.json delete mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/builtinpatterns.md delete mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/custompatterns.md delete mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/patterngroups.md delete mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/_category_.json delete mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/classificationbreakdown.md delete mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/matchcounts.md delete mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/runningscan.md delete mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/_category_.json delete mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/autovscustom.md delete mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/classificationrules.md delete mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/taxonomygroups.md delete mode 100644 docs/accessanalyzer/1.0/troubleshooting/_category_.json delete mode 100644 docs/accessanalyzer/1.0/troubleshooting/commonissues/_category_.json delete mode 100644 docs/accessanalyzer/1.0/troubleshooting/commonissues/connectionfailures.md delete mode 100644 docs/accessanalyzer/1.0/troubleshooting/commonissues/databaseconnectivity.md delete mode 100644 docs/accessanalyzer/1.0/troubleshooting/commonissues/scanerrors.md delete mode 100644 docs/accessanalyzer/1.0/troubleshooting/healthchecks/_category_.json delete mode 100644 docs/accessanalyzer/1.0/troubleshooting/healthchecks/endpoints.md delete mode 100644 docs/accessanalyzer/1.0/troubleshooting/healthchecks/probes.md delete mode 100644 docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/_category_.json delete mode 100644 docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/failedjobs.md delete mode 100644 docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/queues.md delete mode 100644 docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/sidekiq.md delete mode 100644 docs/accessanalyzer/1.0/troubleshooting/observability/_category_.json delete mode 100644 docs/accessanalyzer/1.0/troubleshooting/observability/opentelemetry.md delete mode 100644 docs/accessanalyzer/1.0/troubleshooting/observability/prometheus.md delete mode 100644 docs/accessanalyzer/1.0/troubleshooting/overview.md diff --git a/docs/accessanalyzer/1.0/activitymonitoring/_category_.json b/docs/accessanalyzer/1.0/activitymonitoring/_category_.json deleted file mode 100644 index 0855f40693..0000000000 --- a/docs/accessanalyzer/1.0/activitymonitoring/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Activity Monitoring", - "position": 90, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/activitymonitoring/configuration/_category_.json b/docs/accessanalyzer/1.0/activitymonitoring/configuration/_category_.json deleted file mode 100644 index 4fda61ea66..0000000000 --- a/docs/accessanalyzer/1.0/activitymonitoring/configuration/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Configuration", - "position": 20, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "enablingsyslog" - } -} diff --git a/docs/accessanalyzer/1.0/activitymonitoring/configuration/batchprocessing.md b/docs/accessanalyzer/1.0/activitymonitoring/configuration/batchprocessing.md deleted file mode 100644 index 807ec75106..0000000000 --- a/docs/accessanalyzer/1.0/activitymonitoring/configuration/batchprocessing.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Batch Processing Settings" -description: "Configure batch size and processing intervals" -sidebar_position: 30 -draft: true ---- - -# Batch Processing Settings diff --git a/docs/accessanalyzer/1.0/activitymonitoring/configuration/connectingnam.md b/docs/accessanalyzer/1.0/activitymonitoring/configuration/connectingnam.md deleted file mode 100644 index 3f9bdba5f0..0000000000 --- a/docs/accessanalyzer/1.0/activitymonitoring/configuration/connectingnam.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Connecting Netwrix Activity Monitor" -description: "Configure NAM to send events to Access Analyzer" -sidebar_position: 20 -draft: true ---- - -# Connecting Netwrix Activity Monitor diff --git a/docs/accessanalyzer/1.0/activitymonitoring/configuration/enablingsyslog.md b/docs/accessanalyzer/1.0/activitymonitoring/configuration/enablingsyslog.md deleted file mode 100644 index ed154c8585..0000000000 --- a/docs/accessanalyzer/1.0/activitymonitoring/configuration/enablingsyslog.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Enabling Syslog Ingestion" -description: "Enable the syslog listener for activity data" -sidebar_position: 10 -draft: true ---- - -# Enabling Syslog Ingestion diff --git a/docs/accessanalyzer/1.0/activitymonitoring/overview.md b/docs/accessanalyzer/1.0/activitymonitoring/overview.md deleted file mode 100644 index 1db4669826..0000000000 --- a/docs/accessanalyzer/1.0/activitymonitoring/overview.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Activity Monitoring" -description: "Monitor file access and user activity via Netwrix Activity Monitor" -sidebar_position: 1 -draft: true ---- - -# Activity Monitoring diff --git a/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/_category_.json b/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/_category_.json deleted file mode 100644 index 0f66039da8..0000000000 --- a/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Viewing Activity Data", - "position": 30, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "fileaccessevents" - } -} diff --git a/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/fileaccessevents.md b/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/fileaccessevents.md deleted file mode 100644 index e914857e32..0000000000 --- a/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/fileaccessevents.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "File Access Events" -description: "Viewing file access event data" -sidebar_position: 10 -draft: true ---- - -# File Access Events diff --git a/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/useractivitypatterns.md b/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/useractivitypatterns.md deleted file mode 100644 index b22d570ef1..0000000000 --- a/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/useractivitypatterns.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "User Activity Patterns" -description: "Analyzing user activity trends and patterns" -sidebar_position: 20 -draft: true ---- - -# User Activity Patterns diff --git a/docs/accessanalyzer/1.0/admin/_category_.json b/docs/accessanalyzer/1.0/admin/_category_.json deleted file mode 100644 index 8ba9f88730..0000000000 --- a/docs/accessanalyzer/1.0/admin/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Administration", - "position": 50, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/admin/auditlogs/_category_.json b/docs/accessanalyzer/1.0/admin/auditlogs/_category_.json deleted file mode 100644 index 08737ee73a..0000000000 --- a/docs/accessanalyzer/1.0/admin/auditlogs/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Audit Logs", - "position": 100, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/admin/auditlogs/export.md b/docs/accessanalyzer/1.0/admin/auditlogs/export.md deleted file mode 100644 index 5f46de33f4..0000000000 --- a/docs/accessanalyzer/1.0/admin/auditlogs/export.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: "Log Export" -description: "Exporting audit log data" -sidebar_position: 20 ---- - -# Log Export - -Administrators can export audit log data for external analysis, compliance reporting, or long-term archival. The export feature generates a downloadable file containing the filtered audit log entries. - -## Exporting Logs - -To export audit logs: - -1. Navigate to **Audit Logs** in the sidebar. -2. Apply any desired filters (date range, user, action type, resource type) to narrow the export scope. -3. Click **Export**. -4. Select the export format: - -| Format | Description | -|---|---| -| **CSV** | Comma-separated values, compatible with spreadsheet applications and data analysis tools | -| **JSON** | Structured JSON format, suitable for programmatic processing and SIEM ingestion | - -5. Click **Download** to save the file. - -## Export Scope - -The export includes all audit log entries matching the current filter criteria. If no filters are applied, the export contains all available audit log records. - -:::note -Large exports may take several minutes to generate. The download begins automatically when the file is ready. -::: - -## Use Cases - -- **Compliance Audits** -- Provide auditors with a complete trail of administrative actions over a specified period. -- **SIEM Integration** -- Export logs in JSON format for ingestion into security information and event management platforms. -- **Archival** -- Periodically export and archive audit logs to external storage for long-term retention. - -:::warning -Exported audit log files may contain sensitive information about users and system configuration. Handle exported files in accordance with your organization's data handling policies. -::: diff --git a/docs/accessanalyzer/1.0/admin/auditlogs/overview.md b/docs/accessanalyzer/1.0/admin/auditlogs/overview.md deleted file mode 100644 index fa30bc76ae..0000000000 --- a/docs/accessanalyzer/1.0/admin/auditlogs/overview.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: "Audit Logs" -description: "Viewing system activity and audit trail" -sidebar_position: 10 ---- - -# Audit Logs - -Access Analyzer maintains a comprehensive audit trail of all user actions. Audit logs capture who performed an action, what was changed, and when the event occurred. This data supports security reviews, compliance audits, and incident investigations. - -## Viewing Audit Logs - -Navigate to **Audit Logs** in the sidebar to access the log viewer. The audit log table displays: - -| Column | Description | -|---|---| -| **Timestamp** | Date and time of the action | -| **User** | The user who performed the action | -| **Action** | The type of operation (e.g., Create, Update, Delete, Login, Logout) | -| **Resource** | The affected resource type and identifier | -| **Details** | Additional context about the change, including before and after values where applicable | -| **IP Address** | The client IP from which the action was performed | - -## Filtering and Searching - -Use the table controls to filter audit logs by: - -- **Date range** -- Specify start and end dates. -- **User** -- Filter by a specific user. -- **Action type** -- Show only specific action types. -- **Resource type** -- Filter by resource category (e.g., Source, Scan, User). - -## Log Retention - -Audit logs are retained for the duration configured in application settings. By default, logs are retained indefinitely. - -## Related Topics - -- [Log Export](/docs/accessanalyzer/1_0/admin/auditlogs/export) diff --git a/docs/accessanalyzer/1.0/admin/authentication/_category_.json b/docs/accessanalyzer/1.0/admin/authentication/_category_.json deleted file mode 100644 index b4206ec509..0000000000 --- a/docs/accessanalyzer/1.0/admin/authentication/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Authentication", - "position": 30, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/admin/authentication/overview.md b/docs/accessanalyzer/1.0/admin/authentication/overview.md deleted file mode 100644 index cea13a2a43..0000000000 --- a/docs/accessanalyzer/1.0/admin/authentication/overview.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: "Authentication" -description: "Login workflow and session lifecycle" -sidebar_position: 10 ---- - -# Authentication - -Access Analyzer uses session-based authentication backed by Redis for secure, server-side session storage. All API endpoints under `/api/v1/` require a valid session, except for the login endpoint. - -## Login Workflow - -1. The user submits their **username** and **password** via the login form. -2. The server validates the credentials against the stored Argon2id password hash. -3. On success, a new session is created in Redis and a session cookie is returned to the client. -4. The client includes the session cookie with all subsequent API requests. - -## Session Lifecycle - -Each session progresses through the following states: - -- **Active** -- The session is valid and the user is authenticated. -- **Refreshed** -- The session token has been refreshed before expiration. See [Token Refresh and Expiration](/docs/accessanalyzer/1_0/admin/authentication/tokenrefresh). -- **Expired** -- The session TTL has elapsed and the user must re-authenticate. -- **Revoked** -- An administrator has manually terminated the session. - -## IP Validation - -Access Analyzer validates the client IP address on each request. If a request originates from an IP that does not match the session's originating IP, the session is invalidated and the user must log in again. - -## Related Topics - -- [Token Refresh and Expiration](/docs/accessanalyzer/1_0/admin/authentication/tokenrefresh) -- [Session Monitoring and Revocation](/docs/accessanalyzer/1_0/admin/authentication/sessionmonitoring) diff --git a/docs/accessanalyzer/1.0/admin/authentication/sessionmonitoring.md b/docs/accessanalyzer/1.0/admin/authentication/sessionmonitoring.md deleted file mode 100644 index 15ad434a40..0000000000 --- a/docs/accessanalyzer/1.0/admin/authentication/sessionmonitoring.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: "Session Monitoring and Revocation" -description: "Monitoring active sessions and revoking access" -sidebar_position: 30 ---- - -# Session Monitoring and Revocation - -Administrators can monitor all active sessions across the application and revoke access when needed. This is useful for responding to security incidents or enforcing access policies. - -## Monitoring Active Sessions - -The session monitoring view is accessible from **Users** > **Sessions**. It provides a real-time view of all authenticated sessions, including: - -- **Username** and assigned role -- **Client IP address** and geographic context -- **Session start time** and **last activity** timestamp -- **Remaining TTL** before automatic expiration - -Use the table's filter and sort controls to locate specific sessions by user, IP address, or activity time. - -## Revoking Sessions - -To revoke one or more sessions: - -1. Select the target sessions using the row checkboxes. -2. Click **Revoke Selected**. -3. Confirm the action in the dialog. - -Revocation is immediate. The affected sessions are removed from Redis and all subsequent requests using those session tokens return `401 Unauthorized`. - -## Bulk Revocation - -To revoke all sessions for a specific user, navigate to the user's detail page and click **Revoke All Sessions**. This is recommended when a user account may be compromised. - -:::warning -Session revocation cannot be undone. Affected users must log in again to regain access. -::: diff --git a/docs/accessanalyzer/1.0/admin/authentication/tokenrefresh.md b/docs/accessanalyzer/1.0/admin/authentication/tokenrefresh.md deleted file mode 100644 index ee1dbd8250..0000000000 --- a/docs/accessanalyzer/1.0/admin/authentication/tokenrefresh.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: "Token Refresh and Expiration" -description: "How access tokens are refreshed and session expiration" -sidebar_position: 20 ---- - -# Token Refresh and Expiration - -Access Analyzer sessions have a configurable time-to-live (TTL). To prevent unnecessary re-authentication, sessions are automatically refreshed during active use. - -## How Token Refresh Works - -When a user makes an API request and the session is past the halfway point of its TTL, the server automatically issues a new session token. This process is transparent to the user: - -1. The client sends a request with the current session cookie. -2. The server detects that the session has passed 50% of its TTL. -3. A new session token is generated and the old token is invalidated. -4. The response includes the updated session cookie. - -## Session Expiration - -Sessions expire when the full TTL elapses without any qualifying refresh. When a session expires: - -- All subsequent API requests return a `401 Unauthorized` response. -- The user is redirected to the login page. -- The expired session record is automatically purged from Redis. - -## Configuration - -Session TTL and refresh behavior are configured in the application settings. See [Session and Token TTL](/docs/accessanalyzer/1_0/admin/settings/sessionttl) for configuration details. - -:::note -Token refresh only occurs during active requests. Background tabs or idle browser windows do not trigger a refresh. -::: diff --git a/docs/accessanalyzer/1.0/admin/iam/_category_.json b/docs/accessanalyzer/1.0/admin/iam/_category_.json deleted file mode 100644 index 762c39d494..0000000000 --- a/docs/accessanalyzer/1.0/admin/iam/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "IAM Services", - "position": 80, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/admin/iam/identitiesentitlements.md b/docs/accessanalyzer/1.0/admin/iam/identitiesentitlements.md deleted file mode 100644 index d0fedf9ee1..0000000000 --- a/docs/accessanalyzer/1.0/admin/iam/identitiesentitlements.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: "Viewing Identities and Entitlements" -description: "Browsing synced users and their permissions" -sidebar_position: 30 ---- - -# Viewing Identities and Entitlements - -After identity synchronization completes, administrators and viewers can browse the unified identity directory and review entitlements across all scanned sources. - -## Identity List - -Navigate to **IAM** > **Identities** to view all synced identities. The table displays: - -| Column | Description | -|---|---| -| **Display Name** | The user or group name | -| **Type** | User or Group | -| **Provider** | Source directory (Active Directory, Entra ID, Local Groups) | -| **Email** | Associated email address, if available | -| **Group Count** | Number of groups the identity belongs to | -| **Last Synced** | Timestamp of the most recent sync | - -Use the filter controls to narrow results by provider, type, or keyword search. - -## Entitlement Details - -Click an identity to open the detail view, which includes: - -- **Group Memberships** -- All groups the identity belongs to, including nested group membership. -- **Resource Access** -- A list of sources and resources the identity can access, with the effective permission level. -- **Permission Paths** -- Links to the [Permission Path Analysis](/docs/accessanalyzer/1_0/admin/iam/permissionpaths) for each access entry, showing how the permission was granted. - -## Cross-Provider Correlation - -When the same user exists in multiple directories, Access Analyzer correlates these identities and displays a unified view. Correlated accounts are indicated with a badge showing the linked providers. diff --git a/docs/accessanalyzer/1.0/admin/iam/identitysync.md b/docs/accessanalyzer/1.0/admin/iam/identitysync.md deleted file mode 100644 index 784bd209da..0000000000 --- a/docs/accessanalyzer/1.0/admin/iam/identitysync.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: "Identity Sync Process" -description: "How identities are synchronized from IAM providers" -sidebar_position: 20 ---- - -# Identity Sync Process - -Identity synchronization imports user and group data from configured IAM providers into Access Analyzer. This data forms the foundation for entitlement analysis and permission path reporting. - -## How Sync Works - -The identity sync process performs the following steps: - -1. Connects to each configured IAM source (Active Directory, Entra ID, or Local Groups) using the associated service account credentials. -2. Retrieves user accounts, groups, and membership relationships. -3. Normalizes identity data into a unified format across providers. -4. Stores the synchronized identities in the Access Analyzer database. -5. Correlates identities across multiple providers when the same user appears in more than one directory. - -## Triggering a Sync - -Identity sync occurs automatically during access scan execution. It can also be triggered manually: - -1. Navigate to **IAM** in the sidebar. -2. Click **Sync Now**. -3. Monitor the sync progress in the status indicator. - -## Sync Frequency - -Each access scan triggers a fresh identity sync for its target sources. For environments that change frequently, schedule access scans at regular intervals to keep identity data current. - -## Sync Status - -| Status | Description | -|---|---| -| **In Progress** | Sync is actively importing identity data | -| **Completed** | Sync finished successfully with a timestamp | -| **Failed** | Sync encountered an error; check system logs for details | - -:::note -Identity sync only imports identity metadata (usernames, group names, memberships). It does not import passwords or other credential data. -::: diff --git a/docs/accessanalyzer/1.0/admin/iam/overview.md b/docs/accessanalyzer/1.0/admin/iam/overview.md deleted file mode 100644 index 60b42bffc2..0000000000 --- a/docs/accessanalyzer/1.0/admin/iam/overview.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: "IAM Services" -description: "Configuring identity and access management integrations" -sidebar_position: 10 ---- - -# IAM Services - -The IAM section provides tools for synchronizing identities from external directories and analyzing access entitlements across your environment. This enables centralized visibility into who has access to what resources and how that access was granted. - -## Supported IAM Providers - -Access Analyzer synchronizes identity data from the following sources: - -| Provider | Identity Data | -|---|---| -| **Active Directory** | Users, groups, group memberships, organizational units | -| **Entra ID** | Users, groups, application role assignments | -| **Local Groups** | Local users and group memberships on Windows servers | - -## Key Capabilities - -- **Identity Synchronization** -- Import users and groups from configured IAM providers. See [Identity Sync Process](/docs/accessanalyzer/1_0/admin/iam/identitysync). -- **Identities and Entitlements** -- Browse synced identities and view their effective permissions across sources. See [Viewing Identities and Entitlements](/docs/accessanalyzer/1_0/admin/iam/identitiesentitlements). -- **Permission Path Analysis** -- Trace the path from a user to a resource to understand how access was granted. See [Permission Path Analysis](/docs/accessanalyzer/1_0/admin/iam/permissionpaths). - -## Prerequisites - -Before using IAM features, ensure that: - -- At least one Active Directory, Entra ID, or Local Groups source is configured with valid credentials. -- An access scan has been completed for the target sources. diff --git a/docs/accessanalyzer/1.0/admin/iam/permissionpaths.md b/docs/accessanalyzer/1.0/admin/iam/permissionpaths.md deleted file mode 100644 index c119a02184..0000000000 --- a/docs/accessanalyzer/1.0/admin/iam/permissionpaths.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: "Permission Path Analysis" -description: "Analyzing permission paths and access relationships" -sidebar_position: 40 ---- - -# Permission Path Analysis - -Permission path analysis traces the chain of access from an identity to a resource, showing every group membership, permission assignment, and inheritance step that grants access. This is essential for understanding why a user has access to a particular resource. - -## Viewing Permission Paths - -To view permission paths for a specific identity: - -1. Navigate to **IAM** > **Identities** and select the target identity. -2. In the **Resource Access** section, click the **View Path** link next to any resource entry. - -The permission path visualization displays the chain as a directional graph: - -**User** > **Group** > **Nested Group** > **Permission Assignment** > **Resource** - -## Path Components - -| Component | Description | -|---|---| -| **Identity** | The starting user or group | -| **Group Membership** | Direct or nested group that the identity belongs to | -| **Permission Entry** | The specific ACL or role assignment that grants access | -| **Resource** | The target file share, site, directory object, or folder | - -## Use Cases - -- **Access Reviews** -- Determine whether a user's access is appropriate and through which path it was granted. -- **Least Privilege Analysis** -- Identify overly broad group memberships that grant unintended access. -- **Incident Response** -- Trace access paths for a compromised account to assess the scope of exposure. - -:::note -Permission paths are computed from the most recent access scan results. Run a new scan to capture changes in group memberships or permission assignments. -::: diff --git a/docs/accessanalyzer/1.0/admin/navigate/_category_.json b/docs/accessanalyzer/1.0/admin/navigate/_category_.json deleted file mode 100644 index b9960d7f84..0000000000 --- a/docs/accessanalyzer/1.0/admin/navigate/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Navigating the Web Interface", - "position": 10, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/admin/navigate/datatables.md b/docs/accessanalyzer/1.0/admin/navigate/datatables.md deleted file mode 100644 index 4c976fa57d..0000000000 --- a/docs/accessanalyzer/1.0/admin/navigate/datatables.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: "Data Tables" -description: "Sorting, filtering, and pagination in data tables" -sidebar_position: 30 ---- - -# Data Tables - -Data tables are used throughout the Access Analyzer interface to display collections of records such as sources, scans, users, and audit log entries. Each table supports sorting, filtering, and pagination. - -## Sorting - -Click a column header to sort the table by that column. Click the same header again to toggle between ascending and descending order. A directional arrow icon indicates the current sort direction. - -## Filtering - -Use the filter controls above the table to narrow results: - -- **Text search** -- Enter a keyword to filter rows that match across visible columns. -- **Column filters** -- Some tables provide dropdown filters for specific columns such as status, type, or date range. - -## Pagination - -Tables with large datasets are paginated. Use the controls at the bottom of the table to: - -- Navigate between pages using **Previous** and **Next** buttons. -- Select the number of rows displayed per page (e.g., 10, 25, 50, 100). - -## Bulk Actions - -On supported tables, select one or more rows using the checkbox column to enable bulk actions. Available bulk actions vary by context and may include **Delete**, **Run Scan**, or **Export**. - -:::note -Table state (sort order, active filters, current page) resets when you navigate away from the page. -::: diff --git a/docs/accessanalyzer/1.0/admin/navigate/overview.md b/docs/accessanalyzer/1.0/admin/navigate/overview.md deleted file mode 100644 index 9662e7ffe0..0000000000 --- a/docs/accessanalyzer/1.0/admin/navigate/overview.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: "Navigating the Web Interface" -description: "Overview of the Access Analyzer web interface" -sidebar_position: 10 ---- - -# Navigating the Web Interface - -Netwrix Access Analyzer provides a web-based interface for managing all configuration and reporting tasks. The interface is organized into a persistent sidebar for primary navigation and a main content area that displays contextual data tables, forms, and dashboards. - -## Interface Layout - -The web interface consists of the following regions: - -- **Sidebar** -- The left-hand navigation panel provides access to all major sections including Sources, Scans, IAM, Sensitive Data, Settings, and Audit Logs. See [Sidebar Navigation](/docs/accessanalyzer/1_0/admin/navigate/sidebar) for details. -- **Header bar** -- Displays the current user, session status, and a logout control. -- **Main content area** -- Renders the active page content including data tables, detail views, and configuration forms. - -## Key Concepts - -- Most list views use paginated [Data Tables](/docs/accessanalyzer/1_0/admin/navigate/datatables) with sorting, filtering, and search capabilities. -- Breadcrumbs at the top of the content area indicate your current location in the navigation hierarchy. -- Action buttons such as **Create**, **Edit**, and **Delete** appear contextually based on the active page and your user role. - -:::note -The interface requires a modern web browser with JavaScript enabled. Supported browsers include the latest versions of Chrome, Edge, and Firefox. -::: diff --git a/docs/accessanalyzer/1.0/admin/navigate/sidebar.md b/docs/accessanalyzer/1.0/admin/navigate/sidebar.md deleted file mode 100644 index db30881ccf..0000000000 --- a/docs/accessanalyzer/1.0/admin/navigate/sidebar.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: "Sidebar Navigation" -description: "Using the sidebar to navigate between sections" -sidebar_position: 20 ---- - -# Sidebar Navigation - -The sidebar is the primary navigation element in the Access Analyzer web interface. It remains visible on every page and provides direct access to all major administration sections. - -## Sidebar Sections - -The sidebar contains the following top-level entries: - -| Section | Purpose | -|---|---| -| **Dashboard** | Application overview and summary metrics | -| **Sources** | Manage data sources and source groups | -| **Scans** | Create, schedule, and monitor scans | -| **IAM** | View synced identities, entitlements, and permission paths | -| **Sensitive Data** | Configure classification patterns and taxonomy rules | -| **Service Accounts** | Manage credentials for source connections | -| **Settings** | Application-wide configuration | -| **Audit Logs** | Review user action history | -| **System Logs** | View application and job processing logs | -| **Users** | Manage user accounts and sessions | - -## Collapsible Groups - -Some sidebar entries expand to reveal sub-items. Click a section label to toggle its children. The currently active page is highlighted with a visual indicator. - -## Role-Based Visibility - -Users with the **Viewer** role see a reduced sidebar. Administrative sections such as **Settings** and **Users** are hidden for non-administrator accounts. diff --git a/docs/accessanalyzer/1.0/admin/overview.md b/docs/accessanalyzer/1.0/admin/overview.md deleted file mode 100644 index 0b759ccd84..0000000000 --- a/docs/accessanalyzer/1.0/admin/overview.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: "Administration" -description: "Manage users, sources, scans, and system settings" -sidebar_position: 1 ---- - -# Administration - -The Administration section provides tools for configuring and managing all aspects of Netwrix Access Analyzer. From here, administrators can control user access, define data sources, configure scans, and maintain system settings. - -## Admin Sections - -| Section | Description | -|---|---| -| [Navigation](/docs/accessanalyzer/1_0/admin/navigate/overview) | Learn how to navigate the web interface, use the sidebar, and interact with data tables | -| [Users](/docs/accessanalyzer/1_0/admin/users/overview) | Create and manage user accounts, assign roles, and monitor sessions | -| [Authentication](/docs/accessanalyzer/1_0/admin/authentication/overview) | Configure login workflows, session lifecycle, and token management | -| [Sources](/docs/accessanalyzer/1_0/admin/sources/overview) | Add and manage data sources for scanning | -| [Service Accounts](/docs/accessanalyzer/1_0/admin/serviceaccounts/overview) | Manage credentials used to connect to data sources | -| [Scans](/docs/accessanalyzer/1_0/admin/scans/overview) | Create, schedule, and monitor access and sensitive data scans | -| [Sensitive Data](/docs/accessanalyzer/1_0/admin/sensitivedata/overview) | Configure classification patterns, taxonomy groups, and compliance mappings | -| [IAM](/docs/accessanalyzer/1_0/admin/iam/overview) | Synchronize identities and analyze entitlements and permission paths | -| [Settings](/docs/accessanalyzer/1_0/admin/settings/overview) | Configure application-wide settings, scan limits, and feature flags | -| [Audit Logs](/docs/accessanalyzer/1_0/admin/auditlogs/overview) | Review and export the full user action audit trail | -| [System Logs](/docs/accessanalyzer/1_0/admin/systemlogs) | View application-level system logs and Sidekiq job monitoring | - -:::note -Only users with the **Administrator** role have full access to all administration functions. Users with the **Viewer** role have read-only access. -::: diff --git a/docs/accessanalyzer/1.0/admin/scans/_category_.json b/docs/accessanalyzer/1.0/admin/scans/_category_.json deleted file mode 100644 index 27b262b756..0000000000 --- a/docs/accessanalyzer/1.0/admin/scans/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Scan Management", - "position": 60, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/admin/scans/executionhistory.md b/docs/accessanalyzer/1.0/admin/scans/executionhistory.md deleted file mode 100644 index 4afaf84df1..0000000000 --- a/docs/accessanalyzer/1.0/admin/scans/executionhistory.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: "Scan Execution History" -description: "Viewing scan status and execution history" -sidebar_position: 50 ---- - -# Scan Execution History - -Every scan execution is recorded with detailed status information, timing, and result summaries. The execution history provides a complete audit trail of all scan activity. - -## Viewing Execution History - -To view a scan's history: - -1. Navigate to **Scans** and click the target scan. -2. Select the **History** tab in the detail view. - -The history table displays each execution with the following columns: - -| Column | Description | -|---|---| -| **Run ID** | Unique identifier for the execution | -| **Status** | Final status (Completed, Failed, Stopped) | -| **Started At** | Timestamp when the execution began | -| **Completed At** | Timestamp when the execution ended | -| **Duration** | Total elapsed time | -| **Items Processed** | Number of resources scanned | -| **Findings** | Count of access entries or sensitive data matches found | - -## Execution Details - -Click a specific execution row to view detailed results including: - -- Per-source breakdown of items scanned and findings -- Error messages for failed executions -- Resource utilization metrics - -## Retention - -Execution history records are retained indefinitely. To manage storage, administrators can export and archive older records through the [Audit Logs](/docs/accessanalyzer/1_0/admin/auditlogs/overview) export feature. - -:::note -Execution history for deleted scans is also removed. Export any needed data before deleting a scan. -::: diff --git a/docs/accessanalyzer/1.0/admin/scans/overview.md b/docs/accessanalyzer/1.0/admin/scans/overview.md deleted file mode 100644 index fb917e14a4..0000000000 --- a/docs/accessanalyzer/1.0/admin/scans/overview.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: "Scan Management" -description: "Creating and managing scans" -sidebar_position: 10 ---- - -# Scan Management - -Scans are the core operational unit in Access Analyzer. A scan defines what sources to analyze, what type of analysis to perform, and when to execute. Administrators create and manage scans from the **Scans** section. - -## Creating Scans - -Scans are typically created as part of the **Connect Source** wizard (Step 3), where you configure scan types, options, and scheduling alongside the source group. The wizard creates all scans atomically with the source group and sources. - -Scans can also be managed independently after creation: - -1. Navigate to **Scans** in the sidebar. -2. Select a scan to view or edit its configuration. -3. Modify the schedule, scan options, or other settings. -4. Click **Save**. - -## Scan List - -The scan list displays all configured scans with their name, type, target sources, schedule, last execution status, and next scheduled run time. Use the data table controls to filter and sort. - -## Related Topics - -- [Scan Types](/docs/accessanalyzer/1_0/admin/scans/scantypes) -- [Scheduling Scans](/docs/accessanalyzer/1_0/admin/scans/scheduling) -- [Running and Stopping Scans](/docs/accessanalyzer/1_0/admin/scans/runningstop) -- [Scan Execution History](/docs/accessanalyzer/1_0/admin/scans/executionhistory) diff --git a/docs/accessanalyzer/1.0/admin/scans/runningstop.md b/docs/accessanalyzer/1.0/admin/scans/runningstop.md deleted file mode 100644 index 3df1773d7f..0000000000 --- a/docs/accessanalyzer/1.0/admin/scans/runningstop.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: "Running and Stopping Scans" -description: "Executing scans and graceful stop" -sidebar_position: 40 ---- - -# Running and Stopping Scans - -Administrators can manually trigger scan execution and control running scans through the web interface. These controls are available from the scan detail view and the scan list. - -## Running a Scan Manually - -To start a scan immediately: - -1. Navigate to **Scans** in the sidebar. -2. Locate the scan and click **Run** (or open the detail view and click **Run Now**). -3. The scan status changes to **Running** and progress is displayed in real time. - -## Scan Controls - -While a scan is running, the following controls are available: - -| Action | Description | -|---|---| -| **Pause** | Temporarily suspends scan execution. The scan can be resumed from where it stopped. | -| **Resume** | Continues a paused scan from its last checkpoint. | -| **Stop** | Initiates a graceful stop. The scan finishes processing the current item and then terminates. | - -## Scan Status Values - -| Status | Meaning | -|---|---| -| **Pending** | The scan is queued and waiting to start | -| **Running** | The scan is actively processing | -| **Paused** | The scan is suspended and can be resumed | -| **Completing** | The scan is finishing its current work unit after a stop request | -| **Completed** | The scan finished successfully | -| **Failed** | The scan terminated due to an error | - -:::warning -Stopping a scan does not roll back any data already collected. Partial results are retained and visible in the scan history. -::: diff --git a/docs/accessanalyzer/1.0/admin/scans/scantypes.md b/docs/accessanalyzer/1.0/admin/scans/scantypes.md deleted file mode 100644 index 39ba1911a2..0000000000 --- a/docs/accessanalyzer/1.0/admin/scans/scantypes.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: "Scan Types" -description: "Access, sensitive data, identity sync, and local users scan types" -sidebar_position: 20 ---- - -# Scan Types - -Access Analyzer supports several scan types, each designed to analyze different aspects of your data environment. Scan types are selected during the Connect Source wizard (Step 3) and determine what data is collected and reported. - -## Access Scans - -Access scans analyze permissions and access controls on the target sources. They collect: - -- User and group permission assignments -- Effective access rights -- Permission inheritance paths -- Share and folder-level access control lists - -Access scans are available for **CIFS** (File Server), **SharePoint**, **Active Directory**, and **Local Groups** source types. - -For File Server sources, access scans support additional configuration options including share filtering, scan depth, file-level permissions, hidden share enumeration, and worker threads. See [CIFS Connector](/docs/accessanalyzer/1_0/connectors/source/cifs/connectionconfig) for details. - -## Sensitive Data Scans - -Sensitive data scans inspect file content to identify data matching configured classification patterns. They detect: - -- Personally identifiable information (PII) -- Financial data (credit card numbers, bank account numbers) -- Protected health information (PHI) -- Credentials and secrets -- Custom patterns defined in [Sensitive Data Configuration](/docs/accessanalyzer/1_0/admin/sensitivedata/overview) - -Sensitive data scans are available for **CIFS** and **SharePoint** source types only. - -## Identity Sync Scans - -Identity sync scans retrieve users, groups, and permissions from identity providers: - -| Scan | Source Type | Description | -| --- | --- | --- | -| **Active Directory Inventory** | Active Directory | Synchronizes users, groups, OUs, and domain permissions | -| **Users, Groups and Roles** | Entra ID | Synchronizes Azure AD users, groups, directory roles, and optionally sensitivity labels | - -For Entra ID, the identity sync scan is always enabled and cannot be disabled. - -## Local Users and Groups Scans - -When an **Access** scan is enabled for a File Server source, a **Local Users and Groups** scan is automatically created alongside it. This scan collects local user and group account data from each file server, which is used to resolve local account references found in NTFS ACLs. - -This scan type does not require separate configuration — it inherits the same schedule as the access scan. - -## Comparison - -| Feature | Access Scan | Sensitive Data Scan | Identity Sync | Local Users and Groups | -|---|---|---|---|---| -| Analyzes permissions | Yes | No | No | No | -| Inspects file content | No | Yes | No | No | -| Syncs identities | No | No | Yes | Yes | -| Supported sources | CIFS, SharePoint, AD, Local Groups | CIFS, SharePoint | AD, Entra ID | CIFS (auto-created) | - -:::note -A single source can have multiple scan types configured independently, each with its own schedule. -::: diff --git a/docs/accessanalyzer/1.0/admin/scans/scheduling.md b/docs/accessanalyzer/1.0/admin/scans/scheduling.md deleted file mode 100644 index f1088e482d..0000000000 --- a/docs/accessanalyzer/1.0/admin/scans/scheduling.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: "Scheduling Scans" -description: "Configuring cron-based scan schedules" -sidebar_position: 30 ---- - -# Scheduling Scans - -Scans can be configured to run automatically on a recurring schedule using cron expressions. Scheduled scans are processed by the Sidekiq background job system. - -## Setting a Schedule - -To schedule a scan: - -1. Navigate to **Scans** and open the scan detail view. -2. Click **Edit**. -3. In the **Schedule** section, enable **Scheduled Execution**. -4. Enter a cron expression or use the visual schedule builder to define the frequency. -5. Click **Save**. - -## Cron Expression Format - -Schedules use standard five-field cron syntax: - -``` -* * * * * -| | | | | -| | | | +-- Day of week (0-6, Sunday=0) -| | | +---- Month (1-12) -| | +------ Day of month (1-31) -| +-------- Hour (0-23) -+---------- Minute (0-59) -``` - -**Examples:** - -| Expression | Description | -|---|---| -| `0 2 * * *` | Daily at 2:00 AM | -| `0 0 * * 0` | Weekly on Sunday at midnight | -| `0 6 1 * *` | Monthly on the 1st at 6:00 AM | -| `0 */4 * * *` | Every 4 hours | - -## Disabling a Schedule - -To stop a scan from running automatically, edit the scan and disable **Scheduled Execution**. The scan configuration is preserved and can be re-enabled later or run manually. - -:::note -All schedule times are interpreted in the server's configured timezone. -::: diff --git a/docs/accessanalyzer/1.0/admin/sensitivedata/_category_.json b/docs/accessanalyzer/1.0/admin/sensitivedata/_category_.json deleted file mode 100644 index 6b56ea467a..0000000000 --- a/docs/accessanalyzer/1.0/admin/sensitivedata/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Sensitive Data Configuration", - "position": 70, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/admin/sensitivedata/customclassification.md b/docs/accessanalyzer/1.0/admin/sensitivedata/customclassification.md deleted file mode 100644 index 732fcd762f..0000000000 --- a/docs/accessanalyzer/1.0/admin/sensitivedata/customclassification.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: "Custom Classification" -description: "Creating custom classification rules" -sidebar_position: 40 ---- - -# Custom Classification - -In addition to built-in patterns, administrators can create custom classification rules to detect organization-specific sensitive data types. Custom rules use regular expressions and integrate with the existing pattern and taxonomy group framework. - -## Creating a Custom Pattern - -To create a custom pattern: - -1. Navigate to **Sensitive Data** > **Pattern Groups**. -2. Select an existing group or click **Create Group** to define a new pattern group. -3. Click **Add Pattern**. -4. Complete the following fields: - -| Field | Description | -|---|---| -| **Name** | A descriptive label (e.g., "Internal Employee ID") | -| **Regex** | The regular expression to match against file content | -| **Confidence** | Expected accuracy level: **High**, **Medium**, or **Low** | -| **Description** | Optional notes about what the pattern detects | - -5. Click **Save**. - -## Creating a Custom Pattern Group - -Custom pattern groups organize related custom patterns under a shared label. To create a group: - -1. Click **Create Group** from the Pattern Groups page. -2. Enter a **Name** and optional **Description**. -3. Add one or more patterns to the group. -4. Click **Save**. - -## Mapping Custom Patterns to Taxonomy Groups - -To include custom patterns in compliance reporting, associate the custom pattern group with one or more taxonomy groups. Edit the taxonomy group and add the custom pattern group to its list of associated patterns. - -:::warning -Test custom regex patterns thoroughly before enabling them in production scans. Overly broad patterns can generate excessive false positives and impact scan performance. -::: diff --git a/docs/accessanalyzer/1.0/admin/sensitivedata/overview.md b/docs/accessanalyzer/1.0/admin/sensitivedata/overview.md deleted file mode 100644 index ba8d0bb074..0000000000 --- a/docs/accessanalyzer/1.0/admin/sensitivedata/overview.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: "Sensitive Data Configuration" -description: "Configuring patterns and classification rules" -sidebar_position: 10 ---- - -# Sensitive Data Configuration - -The Sensitive Data section allows administrators to configure how Access Analyzer identifies and classifies sensitive information during scans. Classification is driven by regex-based patterns organized into pattern groups and taxonomy groups. - -## How Classification Works - -During a sensitive data scan, Access Analyzer inspects file content against all enabled patterns. When a match is found, the file is tagged with the corresponding classification labels and compliance framework mappings. - -## Configuration Components - -| Component | Description | -|---|---| -| [Pattern Groups](/docs/accessanalyzer/1_0/admin/sensitivedata/patterngroups) | Collections of regex patterns that define what constitutes sensitive data (e.g., PII, Credentials) | -| [Taxonomy Groups](/docs/accessanalyzer/1_0/admin/sensitivedata/taxonomygroups) | Compliance-oriented groupings that map patterns to regulatory frameworks (e.g., GDPR, HIPAA) | -| [Custom Classification](/docs/accessanalyzer/1_0/admin/sensitivedata/customclassification) | User-defined patterns and rules for organization-specific data types | - -## Built-in Categories - -Access Analyzer ships with built-in patterns for common sensitive data categories: - -- **PII** -- Social Security numbers, email addresses, phone numbers, names -- **Credentials** -- API keys, passwords, connection strings, tokens -- **PHI** -- Medical record numbers, diagnosis codes, patient identifiers -- **Financial** -- Credit card numbers, bank account numbers, routing numbers - -:::note -Built-in patterns cannot be deleted but can be disabled if they are not relevant to your environment. -::: diff --git a/docs/accessanalyzer/1.0/admin/sensitivedata/patterngroups.md b/docs/accessanalyzer/1.0/admin/sensitivedata/patterngroups.md deleted file mode 100644 index 2179380a16..0000000000 --- a/docs/accessanalyzer/1.0/admin/sensitivedata/patterngroups.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: "Patterns and Pattern Groups" -description: "Managing regex patterns and pattern groups" -sidebar_position: 20 ---- - -# Patterns and Pattern Groups - -Patterns are regular expressions that Access Analyzer uses to identify sensitive data within file content. Patterns are organized into groups for easier management and selective enablement. - -## Pattern Groups - -A pattern group is a named collection of related patterns. Built-in groups include: - -| Group | Examples | -|---|---| -| **PII** | Social Security numbers, driver's license numbers, passport numbers | -| **Credentials** | API keys, passwords in config files, SSH private keys | -| **PHI** | Medical record numbers, health plan IDs, diagnosis codes | -| **Financial** | Credit card numbers (Visa, MasterCard, Amex), IBAN, routing numbers | - -## Managing Patterns - -To view and manage patterns within a group: - -1. Navigate to **Sensitive Data** > **Pattern Groups**. -2. Select a group to view its patterns. -3. Each pattern displays its name, regex expression, and enabled/disabled status. - -Administrators can enable or disable individual patterns within a group. Disabled patterns are excluded from scan matching. - -## Pattern Fields - -| Field | Description | -|---|---| -| **Name** | Descriptive label for the pattern | -| **Regex** | The regular expression used for matching | -| **Confidence** | Expected match accuracy (High, Medium, Low) | -| **Enabled** | Whether the pattern is active during scans | - -:::note -Changes to pattern enablement take effect on the next scan execution. Running scans use the configuration that was active at scan start time. -::: diff --git a/docs/accessanalyzer/1.0/admin/sensitivedata/taxonomygroups.md b/docs/accessanalyzer/1.0/admin/sensitivedata/taxonomygroups.md deleted file mode 100644 index ff36f4f0b9..0000000000 --- a/docs/accessanalyzer/1.0/admin/sensitivedata/taxonomygroups.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: "Taxonomy Groups and Rules" -description: "Configuring taxonomy-based data classification" -sidebar_position: 30 ---- - -# Taxonomy Groups and Rules - -Taxonomy groups map pattern detections to compliance frameworks and regulatory standards. They provide a compliance-oriented view of sensitive data findings. - -## Built-in Compliance Mappings - -Access Analyzer includes pre-configured taxonomy groups aligned to major regulatory frameworks: - -| Taxonomy Group | Framework | Relevant Data Types | -|---|---|---| -| **GDPR** | General Data Protection Regulation | PII, personal data, EU resident identifiers | -| **CCPA** | California Consumer Privacy Act | PII, consumer records, financial identifiers | -| **HIPAA** | Health Insurance Portability and Accountability Act | PHI, medical records, health plan data | -| **PCI DSS** | Payment Card Industry Data Security Standard | Credit card numbers, cardholder data | -| **GLBA** | Gramm-Leach-Bliley Act | Financial records, account numbers | -| **CMMC** | Cybersecurity Maturity Model Certification | Controlled unclassified information, credentials | - -## How Taxonomy Mapping Works - -Each taxonomy group references one or more pattern groups. When a sensitive data scan produces a match against a pattern, the finding is automatically tagged with all associated taxonomy labels. This enables compliance-focused reporting without additional configuration. - -## Managing Taxonomy Groups - -To view taxonomy group configuration: - -1. Navigate to **Sensitive Data** > **Taxonomy Groups**. -2. Select a group to view its associated patterns and compliance mappings. - -Administrators can enable or disable taxonomy groups to control which compliance labels appear in scan results. - -:::note -Built-in taxonomy groups are updated with product releases to reflect changes in regulatory standards. -::: diff --git a/docs/accessanalyzer/1.0/admin/serviceaccounts/_category_.json b/docs/accessanalyzer/1.0/admin/serviceaccounts/_category_.json deleted file mode 100644 index 85d0158bb9..0000000000 --- a/docs/accessanalyzer/1.0/admin/serviceaccounts/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Service Accounts", - "position": 50, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/admin/serviceaccounts/associating.md b/docs/accessanalyzer/1.0/admin/serviceaccounts/associating.md deleted file mode 100644 index cd3479356a..0000000000 --- a/docs/accessanalyzer/1.0/admin/serviceaccounts/associating.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: "Associating with Sources" -description: "Linking service accounts to data sources" -sidebar_position: 30 ---- - -# Associating with Sources - -Each data source requires an associated service account to authenticate when connecting to the target environment. A single service account can be shared across multiple sources of compatible types. - -## Assigning a Service Account to a Source - -Service accounts are assigned during source creation or by editing an existing source: - -1. Navigate to **Sources** and open the source detail view. -2. Click **Edit**. -3. In the **Service Account** field, select the desired account from the dropdown. -4. Click **Save**. - -The dropdown only shows service accounts with a credential type compatible with the selected source type. - -## Changing the Associated Account - -To switch a source to a different service account, edit the source and select a new account. The change takes effect on the next scan execution. Running scans continue to use the previously assigned account until completion. - -## Disassociating a Service Account - -To remove a service account association, edit the source and clear the **Service Account** field, then assign a replacement. Sources cannot be saved without a service account. - -:::note -Verify connectivity after changing service account associations by running a [Test Connection](/docs/accessanalyzer/1_0/admin/sources/testconnections). -::: - -## Compatibility Matrix - -| Source Type | Username/Password | OAuth2 Client Credentials | Certificate | -|---|---|---|---| -| CIFS | Yes | No | No | -| SharePoint | No | Yes | Yes | -| Active Directory | Yes | No | No | -| Entra ID | No | Yes | Yes | -| Local Groups | Yes | No | No | diff --git a/docs/accessanalyzer/1.0/admin/serviceaccounts/credentialtypes.md b/docs/accessanalyzer/1.0/admin/serviceaccounts/credentialtypes.md deleted file mode 100644 index 7dc69e4b2f..0000000000 --- a/docs/accessanalyzer/1.0/admin/serviceaccounts/credentialtypes.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: "Credential Types" -description: "Supported credential types and configurations" -sidebar_position: 20 ---- - -# Credential Types - -Access Analyzer supports three credential types for service accounts. The appropriate type depends on the target source and its authentication requirements. Service accounts can be created ahead of time from the **Service Accounts** page, or inline during the Connect Source wizard. - -## Supported Types - -| Credential Type | Description | Typical Use | -|---|---|---| -| **Username/Password** | Standard username and password pair | CIFS file shares, Active Directory, Local Groups | -| **OAuth2 Client Credentials** | Client ID and client secret for OAuth2 flows | Entra ID | -| **Certificate** | X.509 certificate with private key | SharePoint Online | - -## Username/Password - -Provide a **Username** and **Password**. The password is encrypted at rest. For Active Directory and file server sources, use the `DOMAIN\username` or `username@domain.com` format. - -Used by the **File Server** and **Active Directory** wizards. During the wizard, click **+ Create New Account** to create a username/password service account inline. - -## OAuth2 Client Credentials - -Provide a **Client ID** and **Client Secret**. These credentials are used in the OAuth2 client credentials grant flow to obtain an access token from the identity provider. - -Used by the **Entra ID** wizard. The Client ID and Client Secret come from an Azure AD app registration — see [App Registration and Permissions](/docs/accessanalyzer/1_0/connectors/iam/entraid/appregistration) for setup instructions. - -## Certificate - -Upload a **Certificate** file (PEM or PFX format) and provide the **Private Key** or PFX password. Certificate-based authentication is used for SharePoint Online connections. - -:::note -Credential values are stored encrypted and cannot be viewed after creation. To update credentials, edit the service account and provide new values. -::: diff --git a/docs/accessanalyzer/1.0/admin/serviceaccounts/overview.md b/docs/accessanalyzer/1.0/admin/serviceaccounts/overview.md deleted file mode 100644 index aed048051c..0000000000 --- a/docs/accessanalyzer/1.0/admin/serviceaccounts/overview.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: "Service Accounts" -description: "Managing credentials for data source connections" -sidebar_position: 10 ---- - -# Service Accounts - -Service accounts store the credentials that Access Analyzer uses to connect to and authenticate against data sources. Each service account is configured with a specific credential type and can be associated with one or more sources. - -## Creating a Service Account - -To create a service account: - -1. Navigate to **Service Accounts** in the sidebar. -2. Click **Create Service Account**. -3. Enter a **Name** and optional **Description**. -4. Select the [credential type](/docs/accessanalyzer/1_0/admin/serviceaccounts/credentialtypes) (Username/Password, OAuth2 Client Credentials, or Certificate). -5. Provide the required credential fields. -6. Click **Save**. - -## Service Account List - -The service account list displays all configured accounts with their name, credential type, number of associated sources, and creation date. Credentials are never displayed in plaintext after initial creation. - -## Editing and Deleting - -- **Edit** -- Update the name, description, or credential values. Changing credentials takes effect on the next scan execution. -- **Delete** -- Remove a service account. This operation fails if the account is currently associated with any sources. - -:::warning -Before deleting a service account, disassociate it from all sources. See [Associating with Sources](/docs/accessanalyzer/1_0/admin/serviceaccounts/associating). -::: diff --git a/docs/accessanalyzer/1.0/admin/settings/_category_.json b/docs/accessanalyzer/1.0/admin/settings/_category_.json deleted file mode 100644 index 2e922ee742..0000000000 --- a/docs/accessanalyzer/1.0/admin/settings/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Application Settings", - "position": 90, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/admin/settings/featureflags.md b/docs/accessanalyzer/1.0/admin/settings/featureflags.md deleted file mode 100644 index e40dbea10d..0000000000 --- a/docs/accessanalyzer/1.0/admin/settings/featureflags.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: "Feature Flags" -description: "Runtime feature toggles and configuration" -sidebar_position: 40 ---- - -# Feature Flags - -Feature flags allow administrators to enable or disable specific application capabilities at runtime without restarting the service. Flags are defined in the `app_settings.yml` configuration file and can be overridden through the web interface. - -## Viewing Feature Flags - -Navigate to **Settings** > **Feature Flags** to see all available flags, their current state, and descriptions. - -## Configuration File - -Feature flags are declared in `app_settings.yml` on the application server: - -```yaml -feature_flags: - sensitive_data_scanning: true - identity_correlation: true - audit_log_export: true - advanced_permission_paths: false -``` - -## Overriding via the Web Interface - -To toggle a feature flag: - -1. Navigate to **Settings** > **Feature Flags**. -2. Locate the flag and toggle its state. -3. Click **Save**. - -Web interface overrides take precedence over values in `app_settings.yml`. To revert to the file-based value, click **Reset to Default** next to the flag. - -## Common Feature Flags - -| Flag | Description | -|---|---| -| `sensitive_data_scanning` | Enables or disables the sensitive data scan type | -| `identity_correlation` | Enables cross-provider identity matching in IAM | -| `audit_log_export` | Enables the audit log export functionality | -| `advanced_permission_paths` | Enables detailed permission path visualization | - -:::warning -Disabling a feature flag immediately removes the associated functionality from the web interface for all users. Running operations that depend on a disabled flag may fail. -::: diff --git a/docs/accessanalyzer/1.0/admin/settings/overview.md b/docs/accessanalyzer/1.0/admin/settings/overview.md deleted file mode 100644 index f7268f3fb5..0000000000 --- a/docs/accessanalyzer/1.0/admin/settings/overview.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: "Application Settings" -description: "Global application configuration options" -sidebar_position: 10 ---- - -# Application Settings - -The Settings section provides administrators with controls over global application behavior. Configuration changes made here affect all users and system operations. - -## Settings Categories - -| Category | Description | -|---|---| -| [Concurrent Scan Limits](/docs/accessanalyzer/1_0/admin/settings/scanlimits) | Control the maximum number of scans that can execute simultaneously | -| [Session and Token TTL](/docs/accessanalyzer/1_0/admin/settings/sessionttl) | Configure session duration and token refresh intervals | -| [Feature Flags](/docs/accessanalyzer/1_0/admin/settings/featureflags) | Enable or disable application features at runtime | - -## Accessing Settings - -Navigate to **Settings** in the sidebar. Only users with the **Administrator** role can view and modify settings. - -## Saving Changes - -After modifying a setting, click **Save** to apply the change. Most settings take effect immediately. Settings that require a service restart display a notification indicating when the change will be applied. - -:::warning -Changing application settings can affect system behavior for all users. Review changes carefully before saving, and coordinate with other administrators when modifying production configurations. -::: - -## Configuration File - -Some advanced settings are managed through the `app_settings.yml` configuration file on the server. Settings modified through the web interface override values in the configuration file. See [Feature Flags](/docs/accessanalyzer/1_0/admin/settings/featureflags) for details on file-based configuration. diff --git a/docs/accessanalyzer/1.0/admin/settings/scanlimits.md b/docs/accessanalyzer/1.0/admin/settings/scanlimits.md deleted file mode 100644 index 8711666a0c..0000000000 --- a/docs/accessanalyzer/1.0/admin/settings/scanlimits.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: "Concurrent Scan Limits" -description: "Configuring maximum concurrent scan execution" -sidebar_position: 20 ---- - -# Concurrent Scan Limits - -Access Analyzer limits the number of scans that can run simultaneously to manage system resource consumption. Administrators configure these limits based on available server capacity. - -## Configuration - -To configure scan limits: - -1. Navigate to **Settings** in the sidebar. -2. Locate the **Concurrent Scan Limits** section. -3. Set the desired values and click **Save**. - -## Available Settings - -| Setting | Description | Default | -|---|---|---| -| **Max Concurrent Access Scans** | Maximum number of access scans running at the same time | 5 | -| **Max Concurrent Sensitive Data Scans** | Maximum number of sensitive data scans running at the same time | 3 | -| **Max Total Concurrent Scans** | Combined limit across all scan types | 8 | - -## Behavior When Limits Are Reached - -When a scan is triggered (manually or by schedule) and the concurrent limit has been reached, the scan enters a **Pending** state and is queued. Queued scans start automatically as running scans complete, in first-in-first-out order. - -:::note -Sensitive data scans are typically more resource-intensive than access scans. Consider setting a lower concurrent limit for sensitive data scans to avoid impacting system performance. -::: - -## Monitoring - -View the current number of running and queued scans from the **Scans** list page. The status column indicates whether each scan is **Running**, **Pending**, or **Queued**. diff --git a/docs/accessanalyzer/1.0/admin/settings/sessionttl.md b/docs/accessanalyzer/1.0/admin/settings/sessionttl.md deleted file mode 100644 index 00d6f81382..0000000000 --- a/docs/accessanalyzer/1.0/admin/settings/sessionttl.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: "Session and Token TTL" -description: "Configuring session duration and token refresh intervals" -sidebar_position: 30 ---- - -# Session and Token TTL - -Session and token TTL (time-to-live) settings control how long user sessions remain valid and when tokens are refreshed. These settings balance security requirements with user convenience. - -## Configuration - -To configure session TTL: - -1. Navigate to **Settings** in the sidebar. -2. Locate the **Session Configuration** section. -3. Adjust the values and click **Save**. - -## Available Settings - -| Setting | Description | Default | -|---|---|---| -| **Session TTL** | Maximum lifetime of a session, in minutes | 480 (8 hours) | -| **Idle Timeout** | Time of inactivity before a session expires, in minutes | 60 | -| **Token Refresh Threshold** | Percentage of TTL elapsed before automatic token refresh occurs | 50% | - -## How TTL Affects Users - -- When the **Session TTL** expires, the user is logged out regardless of activity. -- When the **Idle Timeout** elapses without any API requests, the session expires. -- Active sessions are automatically refreshed when the elapsed time exceeds the **Token Refresh Threshold**, extending the session without user intervention. - -See [Token Refresh and Expiration](/docs/accessanalyzer/1_0/admin/authentication/tokenrefresh) for details on the refresh mechanism. - -:::warning -Setting very long session TTLs increases the window of exposure if a session token is compromised. Follow your organization's security policies when configuring these values. -::: - -## Session Storage - -Sessions are stored in Redis. Ensure the Redis instance has sufficient memory to accommodate all active sessions, especially in environments with many concurrent users. diff --git a/docs/accessanalyzer/1.0/admin/sources/_category_.json b/docs/accessanalyzer/1.0/admin/sources/_category_.json deleted file mode 100644 index ac24200ff0..0000000000 --- a/docs/accessanalyzer/1.0/admin/sources/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Data Source Management", - "position": 40, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/admin/sources/editdelete.md b/docs/accessanalyzer/1.0/admin/sources/editdelete.md deleted file mode 100644 index 41b634770e..0000000000 --- a/docs/accessanalyzer/1.0/admin/sources/editdelete.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: "Editing and Deleting Sources" -description: "Modifying and removing data sources" -sidebar_position: 40 ---- - -# Editing and Deleting Sources - -Administrators can modify source configuration or remove sources that are no longer needed. Both operations are available from the source detail view. - -## Editing a Source - -To edit a source: - -1. Navigate to **Sources** and click the target source to open its detail view. -2. Click **Edit**. -3. Update the desired fields such as connection parameters, display name, or associated service account. -4. Click **Save**. - -:::note -The source type cannot be changed after creation. To use a different type, create a new source and delete the old one. -::: - -## Deleting a Source - -To delete a source: - -1. Open the source detail view. -2. Click **Delete**. -3. Confirm the deletion in the dialog. - -:::warning -Deleting a source removes all associated scan configurations and execution history. This action cannot be undone. Export any required scan results before deleting. -::: - -## Impact on Related Resources - -- **Scans** -- Any scans targeting the deleted source are also removed. -- **Source Groups** -- The source is automatically removed from any groups it belonged to. -- **Scan Results** -- Historical scan result data associated with the source is permanently deleted. diff --git a/docs/accessanalyzer/1.0/admin/sources/overview.md b/docs/accessanalyzer/1.0/admin/sources/overview.md deleted file mode 100644 index f23e5217a5..0000000000 --- a/docs/accessanalyzer/1.0/admin/sources/overview.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: "Data Source Management" -description: "Adding and managing data sources" -sidebar_position: 10 ---- - -# Data Source Management - -Sources represent the target environments that Access Analyzer connects to for scanning. Sources are organized into **source groups** — named collections that share a service account and configuration. Administrators create, edit, test, and delete sources from the **Sources** section. - -## Adding Sources - -Sources are created through the **Connect Source** wizard, a 3-step guided workflow: - -1. Navigate to **Sources** in the sidebar. -2. Click **Connect Source** to open the wizard drawer. -3. **Step 1** — Select the [source type](/docs/accessanalyzer/1_0/admin/sources/sourcetypes) (File Server, Active Directory, Entra ID, or SharePoint). -4. **Step 2** — Name the source group, assign a [service account](/docs/accessanalyzer/1_0/admin/serviceaccounts/overview), and add one or more sources. -5. **Step 3** — Configure scan types, scan options, and scheduling. -6. Click **Complete Setup** to create the source group, sources, and scans in one operation. - -The wizard uses the `POST /v1/source-groups/setup` endpoint to create all resources atomically. - -### Source Group Behavior by Type - -| Source Type | Sources per Group | Notes | -| --- | --- | --- | -| **File Server** | Multiple | Add many servers with shared service account and domain | -| **Active Directory** | Multiple | Add multiple domain controllers | -| **Entra ID** | Single | One Azure AD tenant per group | -| **SharePoint Online** | Multiple | Add multiple site collections | - -## Source List - -The sources list displays all configured sources with their name, type, connection status, and associated service account. Use the data table controls to filter by type or search by name. - -## Related Topics - -- [Source Types and Configuration](/docs/accessanalyzer/1_0/admin/sources/sourcetypes) -- [Testing Connections](/docs/accessanalyzer/1_0/admin/sources/testconnections) -- [Editing and Deleting Sources](/docs/accessanalyzer/1_0/admin/sources/editdelete) -- [Source Groups](/docs/accessanalyzer/1_0/admin/sources/sourcegroups) diff --git a/docs/accessanalyzer/1.0/admin/sources/sourcegroups.md b/docs/accessanalyzer/1.0/admin/sources/sourcegroups.md deleted file mode 100644 index 13bce1ba62..0000000000 --- a/docs/accessanalyzer/1.0/admin/sources/sourcegroups.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -title: "Source Groups" -description: "Organizing sources into groups with shared configuration" -sidebar_position: 50 ---- - -# Source Groups - -A source group is a named collection of related sources that share a common service account, configuration, and scan settings. Source groups are the primary organizational unit for sources in Access Analyzer. - -## How Source Groups Work - -Source groups are created through the **Connect Source** wizard, which creates the group, all its sources, and associated scans in a single atomic operation. Each source group has: - -- A **name** to identify the group -- A **source type** (all sources in the group are the same type) -- A **service account** shared by all sources in the group -- One or more **sources** (the actual connection targets) -- One or more **scans** with a shared schedule - -## Source Groups by Type - -| Source Type | Sources per Group | Example | -| --- | --- | --- | -| **File Server** | Multiple servers | `Finance File Servers` with `fs01`, `fs02`, `fs03` — all sharing one service account and domain | -| **Active Directory** | Multiple domain controllers | `Corp AD` with `dc01`, `dc02` | -| **Entra ID** | Single tenant | `Corporate Entra ID` with one Azure AD tenant | -| **SharePoint Online** | Multiple site collections | `Marketing SharePoint` with several sites | - -## Creating a Source Group - -Source groups are created exclusively through the Connect Source wizard: - -1. Navigate to **Sources** in the sidebar -2. Click **Connect Source** -3. Follow the 3-step wizard: select source type, configure sources, set up scans -4. Click **Complete Setup** - -For detailed instructions, see [Adding a Data Source](/docs/accessanalyzer/1_0/gettingstarted/firstscan/addingsource). - -## Viewing Source Groups - -The sources list displays individual sources, each showing its parent source group. You can filter by source group to see all sources within a group. - -## Deleting a Source Group - -Deleting a source group removes the group, all its sources, and all associated scans. - -:::warning -Deleting a source group is permanent and removes all sources and scan configurations within it. Scan execution history is preserved for audit purposes. -::: diff --git a/docs/accessanalyzer/1.0/admin/sources/sourcetypes.md b/docs/accessanalyzer/1.0/admin/sources/sourcetypes.md deleted file mode 100644 index 55f2f7cc4d..0000000000 --- a/docs/accessanalyzer/1.0/admin/sources/sourcetypes.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: "Source Types and Configuration" -description: "Available source types and their configuration parameters" -sidebar_position: 20 ---- - -# Source Types and Configuration - -Access Analyzer supports multiple source types, each targeting a different data environment. The source type determines the required connection parameters and the kinds of scans available. - -## Available Source Types - -| Source Type | Description | Supported Scans | -|---|---|---| -| **CIFS** | Windows file shares accessed via SMB/CIFS protocol | Access, Sensitive Data | -| **SharePoint** | Microsoft SharePoint Online or on-premises sites | Access, Sensitive Data | -| **Active Directory** | On-premises Active Directory domains | Access | -| **Entra ID** | Microsoft Entra ID (formerly Azure AD) tenants | Access | -| **Local Groups** | Local user and group membership on Windows servers | Access | - -## Configuration Parameters - -Each source type requires specific connection details: - -- **CIFS** -- Server hostname or IP, share path, and port number. -- **SharePoint** -- Site URL, authentication method, and tenant ID. -- **Active Directory** -- Domain controller hostname, base DN, and LDAP port. -- **Entra ID** -- Tenant ID, client ID, and authentication secret or certificate. -- **Local Groups** -- Target server hostname or IP address. - -All source types require an associated [service account](/docs/accessanalyzer/1_0/admin/serviceaccounts/overview) with appropriate credentials for the target environment. - -:::note -Source type cannot be changed after creation. To switch types, delete the existing source and create a new one. -::: diff --git a/docs/accessanalyzer/1.0/admin/sources/testconnections.md b/docs/accessanalyzer/1.0/admin/sources/testconnections.md deleted file mode 100644 index ff5de9a3c1..0000000000 --- a/docs/accessanalyzer/1.0/admin/sources/testconnections.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: "Testing Connections" -description: "Validating source connectivity before scanning" -sidebar_position: 30 ---- - -# Testing Connections - -Before running scans, verify that Access Analyzer can reach and authenticate to each configured source using the test connection feature. Connection testing is available both during source creation (in the wizard) and on existing sources. - -## Testing During Source Creation - -The Connect Source wizard includes a **Test Connection** button in Step 2: - -- **File Server** — Tests all servers in parallel. Each server shows its own status: **Connected** (green), **Failed** (red), or **Testing** (spinner). A summary toast shows the overall result (for example, "All 3 connections successful" or "1 of 3 failed"). -- **Entra ID** — Tests the OAuth2 connection to the specified Azure AD tenant. Status appears inline: "Successfully connected to Entra ID" or "Connection failed" with an error message. -- **Active Directory** — Tests connectivity to each domain controller. - -:::note -Connection testing in the wizard is non-blocking. You can proceed to the next step regardless of test results. -::: - -## Testing Existing Sources - -To test an existing source connection: - -1. Navigate to **Sources** in the sidebar. -2. Locate the source in the list and click its row to open the detail view. -3. Click **Test Connection**. -4. Wait for the test to complete. Results appear inline. - -## What Gets Tested - -The test connection operation sends a request to `POST /v1/sources/test-connection` with the source's connection parameters. It validates: - -| Check | Description | -|---|---| -| **Network Reachability** | Confirms the target host and port are accessible from the application server | -| **Authentication** | Verifies the associated service account credentials are accepted | -| **Authorization** | Confirms the service account has sufficient permissions to read the target data | - -## Troubleshooting - -If a connection test fails: - -- Verify the source hostname, port, and path are correct. -- Confirm the service account credentials have not expired or been rotated. -- Check that network firewalls allow traffic between the Access Analyzer server and the target host. -- For Entra ID, verify the Tenant ID is correct and the app registration has the required API permissions. -- Review [System Logs](/docs/accessanalyzer/1_0/admin/systemlogs) for detailed error messages. - -:::note -Connection tests do not scan data. They only validate that the connection can be established and authenticated. -::: diff --git a/docs/accessanalyzer/1.0/admin/systemlogs.md b/docs/accessanalyzer/1.0/admin/systemlogs.md deleted file mode 100644 index 383d3646d2..0000000000 --- a/docs/accessanalyzer/1.0/admin/systemlogs.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: "System Logs" -description: "Viewing and exporting system log data" -sidebar_position: 110 ---- - -# System Logs - -System logs provide visibility into the internal operations of Access Analyzer, including application events, background job processing, and error diagnostics. These logs are distinct from audit logs, which track user actions. - -## Viewing System Logs - -Navigate to **System Logs** in the sidebar to access the log viewer. System logs display application-level events including: - -- Application startup and shutdown events -- Background job execution (scan workers, identity sync) -- Connection errors and retry attempts -- API request errors and exceptions - -## Sidekiq Dashboard - -Access Analyzer uses Sidekiq for background job processing. The Sidekiq dashboard provides real-time monitoring of: - -| View | Description | -|---|---| -| **Queues** | Active job queues and their current depth | -| **Workers** | Currently executing jobs and their runtime | -| **Retries** | Failed jobs scheduled for automatic retry | -| **Dead** | Jobs that have exhausted all retry attempts | -| **Scheduled** | Jobs queued for future execution | - -Access the Sidekiq dashboard from **System Logs** > **Job Monitor**. - -## Log Levels - -System logs are categorized by severity: - -| Level | Description | -|---|---| -| **ERROR** | Failures requiring attention | -| **WARN** | Unexpected conditions that did not cause failures | -| **INFO** | Normal operational events | -| **DEBUG** | Detailed diagnostic output (disabled by default) | - -:::note -Debug-level logging generates significant output and can impact performance. Enable it only for targeted troubleshooting and disable it afterward. -::: diff --git a/docs/accessanalyzer/1.0/admin/users/_category_.json b/docs/accessanalyzer/1.0/admin/users/_category_.json deleted file mode 100644 index 9633707491..0000000000 --- a/docs/accessanalyzer/1.0/admin/users/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "User Management", - "position": 20, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/admin/users/overview.md b/docs/accessanalyzer/1.0/admin/users/overview.md deleted file mode 100644 index 74de4204be..0000000000 --- a/docs/accessanalyzer/1.0/admin/users/overview.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: "User Management" -description: "Creating and managing user accounts" -sidebar_position: 10 ---- - -# User Management - -Access Analyzer supports multi-user access with role-based permissions. Administrators can create, edit, and deactivate user accounts from the **Users** section of the web interface. - -## Creating a User - -To create a new user: - -1. Navigate to **Users** in the sidebar. -2. Click **Create User**. -3. Enter the required fields: **Username**, **Email**, and **Password**. -4. Assign a [role](/docs/accessanalyzer/1_0/admin/users/roles) (Administrator or Viewer). -5. Click **Save**. - -Passwords are hashed using Argon2id before storage. Users must meet the configured password complexity requirements. - -## Managing Users - -From the users list, administrators can: - -- **Edit** a user to update their email, role, or password. -- **Deactivate** a user to revoke access without deleting the account record. -- **Delete** a user to permanently remove the account. - -:::warning -Deleting a user is irreversible. Consider deactivating accounts instead if you need to preserve audit history. -::: - -## Related Topics - -- [Roles and Permissions](/docs/accessanalyzer/1_0/admin/users/roles) -- [Session Management](/docs/accessanalyzer/1_0/admin/users/sessions) diff --git a/docs/accessanalyzer/1.0/admin/users/roles.md b/docs/accessanalyzer/1.0/admin/users/roles.md deleted file mode 100644 index 9c83c8f400..0000000000 --- a/docs/accessanalyzer/1.0/admin/users/roles.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: "Roles and Permissions" -description: "Admin and Viewer role definitions and access levels" -sidebar_position: 20 ---- - -# Roles and Permissions - -Access Analyzer uses a role-based access control model with two built-in roles. Each user is assigned exactly one role at account creation, which determines their access level throughout the application. - -## Role Definitions - -| Capability | Administrator | Viewer | -|---|---|---| -| View dashboards and reports | Yes | Yes | -| View sources, scans, and results | Yes | Yes | -| Create, edit, and delete sources | Yes | No | -| Create, schedule, and run scans | Yes | No | -| Manage service accounts | Yes | No | -| Configure sensitive data rules | Yes | No | -| Manage users and roles | Yes | No | -| Modify application settings | Yes | No | -| View audit logs | Yes | Yes | -| Export audit logs | Yes | No | - -## Administrator - -The **Administrator** role grants full access to all features, including user management, source configuration, scan execution, settings, and audit log exports. At least one administrator account must exist in the system. - -## Viewer - -The **Viewer** role provides read-only access to dashboards, scan results, source listings, and audit logs. Viewers cannot create, modify, or delete any resources. - -:::note -Role assignments can be changed at any time by an administrator through the user edit form. -::: diff --git a/docs/accessanalyzer/1.0/admin/users/sessions.md b/docs/accessanalyzer/1.0/admin/users/sessions.md deleted file mode 100644 index 7af8472d7f..0000000000 --- a/docs/accessanalyzer/1.0/admin/users/sessions.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: "Session Management" -description: "Viewing and managing active user sessions" -sidebar_position: 30 ---- - -# Session Management - -Access Analyzer maintains session state for all authenticated users using Redis-backed server-side sessions. Administrators can view and manage active sessions from the **Users** section. - -## Viewing Active Sessions - -Navigate to **Users** > **Sessions** to see a list of all active sessions. The table displays: - -| Column | Description | -|---|---| -| **User** | The username associated with the session | -| **IP Address** | The client IP from which the session was created | -| **Created At** | Timestamp when the session was initiated | -| **Last Active** | Timestamp of the most recent request | -| **Expires At** | When the session will automatically expire based on the configured TTL | - -## Revoking Sessions - -To revoke a session, select the target row and click **Revoke**. The user will be immediately logged out and must re-authenticate. Administrators can also revoke all sessions for a specific user from the user detail page. - -## Session Security - -- Sessions are validated against the originating IP address. If the client IP changes, the session is invalidated. -- Session TTL is configurable in [Settings](/docs/accessanalyzer/1_0/admin/settings/sessionttl). -- Idle sessions expire automatically after the configured timeout period. - -:::warning -Revoking a session takes effect immediately. The affected user will lose access to any in-progress work that has not been saved. -::: diff --git a/docs/accessanalyzer/1.0/connectors/_category_.json b/docs/accessanalyzer/1.0/connectors/_category_.json deleted file mode 100644 index f7b8ad38d7..0000000000 --- a/docs/accessanalyzer/1.0/connectors/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Connectors", - "position": 60, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/connectors/iam/_category_.json b/docs/accessanalyzer/1.0/connectors/iam/_category_.json deleted file mode 100644 index 47506a72c8..0000000000 --- a/docs/accessanalyzer/1.0/connectors/iam/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "IAM Connectors", - "position": 10, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/connectors/iam/activedirectory/_category_.json b/docs/accessanalyzer/1.0/connectors/iam/activedirectory/_category_.json deleted file mode 100644 index 365d3210fe..0000000000 --- a/docs/accessanalyzer/1.0/connectors/iam/activedirectory/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Active Directory", - "position": 10, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "connectionsetup" - } -} diff --git a/docs/accessanalyzer/1.0/connectors/iam/activedirectory/connectionsetup.md b/docs/accessanalyzer/1.0/connectors/iam/activedirectory/connectionsetup.md deleted file mode 100644 index 3dbcd27070..0000000000 --- a/docs/accessanalyzer/1.0/connectors/iam/activedirectory/connectionsetup.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: "Connection Setup" -description: "Configuring the Active Directory LDAP connection" -sidebar_position: 10 ---- - -# Connection Setup - -Configure the Active Directory connector to synchronize users and groups from your on-premises directory. - -## Prerequisites - -- A domain service account with read access to directory objects — see [Active Directory Requirements](/docs/accessanalyzer/1_0/requirements/connectors/activedirectory) -- Network connectivity from the Access Analyzer VM to a domain controller on port 389 (LDAP) or 636 (LDAPS) - -## Create a Service Account - -1. Navigate to **Service Accounts** in the sidebar -2. Click **Add Service Account** -3. Enter a **Name** (for example, `AD Read-Only Service Account`) -4. Select **Username/Password** as the type -5. Enter the **Username** in `DOMAIN\username` or `user@domain.com` format -6. Enter the **Password** -7. Click **Add service account** - -## Add Active Directory as a Source - -1. Navigate to **Configuration** > **Sources** -2. Click **Add Source** -3. Select **IAM Source** as the category -4. Select **Active Directory** as the source type -5. Select the service account created above -6. Enter the **Host** (domain controller hostname or IP) -7. Enter the **Port** (`389` for LDAP, `636` for LDAPS) -8. Enter the **Domain** (for example, `corp.example.com`) -9. Click **Test Connection** to verify connectivity -10. After a successful test, click **Create Source** - -## Test Connection - -The test connection validates: - -- Network connectivity to the domain controller -- LDAP bind with the provided credentials -- Ability to query directory objects - -If the test fails, verify the domain controller is reachable on the specified port and the credentials are correct. diff --git a/docs/accessanalyzer/1.0/connectors/iam/activedirectory/customattributes.md b/docs/accessanalyzer/1.0/connectors/iam/activedirectory/customattributes.md deleted file mode 100644 index fb620e0bb8..0000000000 --- a/docs/accessanalyzer/1.0/connectors/iam/activedirectory/customattributes.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: "Custom Attributes" -description: "Collecting custom LDAP attributes" -sidebar_position: 40 -draft: true ---- - -# Custom Attributes - -:::note -Custom LDAP attribute collection is planned for a future release of Access Analyzer. This page will be updated when the feature becomes available. -::: diff --git a/docs/accessanalyzer/1.0/connectors/iam/activedirectory/groupmembership.md b/docs/accessanalyzer/1.0/connectors/iam/activedirectory/groupmembership.md deleted file mode 100644 index 397959033f..0000000000 --- a/docs/accessanalyzer/1.0/connectors/iam/activedirectory/groupmembership.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: "Group Membership Mapping" -description: "Transitive group membership resolution" -sidebar_position: 30 ---- - -# Group Membership Mapping - -Access Analyzer resolves transitive (nested) group memberships to build a complete picture of effective access. - -## How It Works - -The Active Directory connector collects: - -1. **Direct memberships** — Users and groups that are immediate members of a group -2. **Nested memberships** — Groups that are members of other groups, creating a hierarchy - -Access Analyzer flattens these hierarchies to determine **effective membership** — the complete list of groups a user belongs to, whether directly or through nesting. - -## Impact on Access Analysis - -Effective group memberships are mapped to entitlements discovered by source connector scans, enabling Access Analyzer to show: - -- All groups that grant a user access to a resource -- Whether access comes from direct or nested group membership -- Overly permissive access through deeply nested group chains diff --git a/docs/accessanalyzer/1.0/connectors/iam/activedirectory/usergroupsync.md b/docs/accessanalyzer/1.0/connectors/iam/activedirectory/usergroupsync.md deleted file mode 100644 index 3be2c6e33e..0000000000 --- a/docs/accessanalyzer/1.0/connectors/iam/activedirectory/usergroupsync.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: "User and Group Sync" -description: "Synchronizing users and groups from Active Directory" -sidebar_position: 20 ---- - -# User and Group Sync - -The Active Directory connector performs a full synchronization of users, groups, and group memberships. - -## What Gets Synchronized - -| Object Type | Data Collected | -| --- | --- | -| **Users** | Display name, SAM account name, UPN, email, distinguished name, enabled status | -| **Groups** | Group name, type (security/distribution), scope (domain local/global/universal), distinguished name | -| **Group memberships** | Direct and nested membership relationships | - -## Running a Sync - -1. Navigate to **Configuration** > **Scans** -2. Create or select a scan configured for the Active Directory source -3. Run the scan — the connector performs a full sync on each execution - -## Sync Behavior - -- Each sync is a **full synchronization** — all users, groups, and memberships are collected -- The connector uses LDAP3 for directory queries -- Duration depends on directory size (number of users and groups) -- Results are stored in the Access Analyzer database and used for identity-to-entitlement mapping diff --git a/docs/accessanalyzer/1.0/connectors/iam/entraid/_category_.json b/docs/accessanalyzer/1.0/connectors/iam/entraid/_category_.json deleted file mode 100644 index d1dd3ba163..0000000000 --- a/docs/accessanalyzer/1.0/connectors/iam/entraid/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Entra ID", - "position": 20, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "appregistration" - } -} diff --git a/docs/accessanalyzer/1.0/connectors/iam/entraid/appregistration.md b/docs/accessanalyzer/1.0/connectors/iam/entraid/appregistration.md deleted file mode 100644 index cdc2d7edef..0000000000 --- a/docs/accessanalyzer/1.0/connectors/iam/entraid/appregistration.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -title: "App Registration and Permissions" -description: "Azure AD app registration and API permissions for Entra ID" -sidebar_position: 10 ---- - -# App Registration and Permissions - -The Entra ID connector uses an Azure AD app registration with OAuth2 client credentials for authentication. You need to create an app registration in Azure and then add its credentials as a service account in Access Analyzer. - -## Create an App Registration - -1. Sign in to the [Azure portal](https://portal.azure.com) -2. Navigate to **Microsoft Entra ID** > **App registrations** -3. Click **New registration** -4. Enter a name (for example, `Netwrix Access Analyzer - Entra ID`) -5. Leave the redirect URI blank -6. Click **Register** - -## Configure API Permissions - -1. In the app registration, go to **API permissions** -2. Click **Add a permission** > **Microsoft Graph** > **Application permissions** -3. Add the following permissions: - - `User.Read.All` - - `Group.Read.All` -4. Click **Grant admin consent** for the permissions - -## Create a Client Secret - -1. Go to **Certificates & secrets** -2. Click **New client secret** -3. Enter a description and expiration period -4. Click **Add** -5. Copy the **Value** immediately — it is not shown again - -## Add Entra ID as a Source in Access Analyzer - -Entra ID sources are created through the **Connect Source** wizard, which guides you through a 3-step process: - -### Step 1 — Select Source Type - -1. Navigate to **Configuration** > **Sources** in Access Analyzer -2. Click **Connect Source** to open the wizard drawer -3. Select **Entra ID** from the source type cards -4. Click **Next** - -### Step 2 — Configure Entra ID - -1. Enter a **Source Group Name** (for example, `Corporate Entra ID`) -2. Select or create a **Service Account**: - - Click **+ Create New Account** to add a new Entra ID service account - - Enter the **Client ID** (Application ID from Azure) and **Client Secret** - - Or select an existing Entra ID service account from the dropdown -3. Enter the **Tenant ID** — this is the Azure AD directory ID in UUID format (for example, `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`) -4. Optionally click **Test Connection** to verify OAuth2 authentication - -:::note -The test connection validates that Access Analyzer can authenticate to the Microsoft Graph API with the provided credentials. Testing is optional — you can proceed without testing. -::: - -### Step 3 — Set Up a Scan - -1. The **Users, Groups and Roles** scan is automatically enabled (cannot be disabled) -2. Configure any additional sync options (for example, **Sync Sensitivity Labels**) -3. Choose when to run the first scan: now, at a scheduled time, or on a recurring schedule -4. Click **Complete Setup** - -After setup, the source group is created and the scan runs according to your selected schedule. - -## Related Topics - -- [User and Group Sync](/docs/accessanalyzer/1_0/connectors/iam/entraid/usergroupsync) — What data is synchronized -- [Entra ID Requirements](/docs/accessanalyzer/1_0/requirements/connectors/entraid) — Permissions and prerequisites diff --git a/docs/accessanalyzer/1.0/connectors/iam/entraid/certificateauth.md b/docs/accessanalyzer/1.0/connectors/iam/entraid/certificateauth.md deleted file mode 100644 index a92d6d15ab..0000000000 --- a/docs/accessanalyzer/1.0/connectors/iam/entraid/certificateauth.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: "Certificate-Based Authentication" -description: "Configuring certificate authentication for Entra ID" -sidebar_position: 30 -draft: true ---- - -# Certificate-Based Authentication - -:::note -Certificate-based authentication for Entra ID is planned for a future release. In v1.0, the Entra ID connector uses OAuth2 client credentials (client secret) authentication. See [App Registration and Permissions](/docs/accessanalyzer/1_0/connectors/iam/entraid/appregistration). -::: diff --git a/docs/accessanalyzer/1.0/connectors/iam/entraid/usergroupsync.md b/docs/accessanalyzer/1.0/connectors/iam/entraid/usergroupsync.md deleted file mode 100644 index 73f1d48a42..0000000000 --- a/docs/accessanalyzer/1.0/connectors/iam/entraid/usergroupsync.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: "User and Group Sync" -description: "Synchronizing users, groups, and roles from Entra ID" -sidebar_position: 20 ---- - -# User and Group Sync - -The Entra ID connector synchronizes users, groups, and roles from your Azure AD tenant into Access Analyzer. This data is used for identity mapping and entitlement analysis across your data sources. - -## What Gets Synchronized - -| Data | Description | -| --- | --- | -| **Users** | All user accounts in the tenant, including display name, UPN, and account status | -| **Groups** | Security groups and Microsoft 365 groups, including membership | -| **Roles** | Directory roles assigned to users and groups | -| **Sensitivity Labels** | Microsoft Purview sensitivity labels (optional — see [Sync Options](#sync-options) below) | - -## How It Works - -When you create an Entra ID source group through the [Connect Source wizard](/docs/accessanalyzer/1_0/gettingstarted/firstscan/addingsource), a **Users, Groups and Roles** scan is automatically configured. This scan is always enabled and cannot be disabled — it runs every time the Entra ID source is scanned. - -The connector authenticates using OAuth2 client credentials and calls the Microsoft Graph API to retrieve identity data from the specified tenant. - -## Sync Options - -During scan setup (Step 3 of the wizard), additional sync options may be available depending on the source type metadata configured on the backend. For example: - -- **Sync Sensitivity Labels** — When enabled, the connector also retrieves Microsoft Purview sensitivity labels assigned to users and groups - -These options appear as toggle switches below the scan type selector on the scan setup page. - -## Scan Scheduling - -The Users, Groups and Roles scan supports three scheduling modes: - -| Mode | Description | -| --- | --- | -| **Run scan now** | Execute immediately after setup completes | -| **Run scan at** | Schedule for a specific date and time | -| **Advanced scheduling** | Configure a recurring cron schedule | - -## Related Topics - -- [App Registration and Permissions](/docs/accessanalyzer/1_0/connectors/iam/entraid/appregistration) — Azure AD setup requirements -- [Entra ID Requirements](/docs/accessanalyzer/1_0/requirements/connectors/entraid) — Permissions and prerequisites diff --git a/docs/accessanalyzer/1.0/connectors/iam/localgroups/_category_.json b/docs/accessanalyzer/1.0/connectors/iam/localgroups/_category_.json deleted file mode 100644 index 19a04b0aec..0000000000 --- a/docs/accessanalyzer/1.0/connectors/iam/localgroups/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Local Groups", - "position": 30, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "powershellsetup" - } -} diff --git a/docs/accessanalyzer/1.0/connectors/iam/localgroups/powershellsetup.md b/docs/accessanalyzer/1.0/connectors/iam/localgroups/powershellsetup.md deleted file mode 100644 index 0144b61557..0000000000 --- a/docs/accessanalyzer/1.0/connectors/iam/localgroups/powershellsetup.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: "PowerShell Remoting Setup" -description: "Configuring WinRM and PowerShell Remoting for Local Groups collection" -sidebar_position: 10 ---- - -# PowerShell Remoting Setup - -The Local Groups connector uses PowerShell Remoting (WinRM) to enumerate local users and groups on Windows machines. - -## Prerequisites - -- WinRM must be enabled on each target machine -- A service account with local administrator access or membership in the Remote Management Users group -- Network connectivity from Access Analyzer to target machines on port 5985 (HTTP) or 5986 (HTTPS) - -## Enable WinRM on Target Machines - -### Single Machine - -Run the following command in an elevated PowerShell prompt: - -```powershell -Enable-PSRemoting -Force -``` - -### Domain-Wide via Group Policy - -1. Open **Group Policy Management** -2. Navigate to **Computer Configuration** > **Administrative Templates** > **Windows Components** > **Windows Remote Management (WinRM)** > **WinRM Service** -3. Enable **Allow remote server management through WinRM** -4. Set the IPv4/IPv6 filter to `*` or specific IP ranges - -## Create a Service Account - -1. Navigate to **Service Accounts** in Access Analyzer -2. Click **Add Service Account** -3. Enter a **Name** (for example, `Local Groups - WinRM`) -4. Select **Username/Password** as the type -5. Enter the **Username** in `MACHINE\username` or `DOMAIN\username` format -6. Enter the **Password** -7. Click **Add service account** - -## Add Local Groups as a Source - -1. Navigate to **Configuration** > **Sources** -2. Click **Add Source** > **IAM Source** > **Local Groups** -3. Select the service account -4. Enter the **Host** (target machine hostname or IP) -5. Enter the **Port** (`5985` for HTTP, `5986` for HTTPS) -6. Click **Test Connection** -7. Click **Create Source** diff --git a/docs/accessanalyzer/1.0/connectors/iam/localgroups/usergroupcollection.md b/docs/accessanalyzer/1.0/connectors/iam/localgroups/usergroupcollection.md deleted file mode 100644 index 2fed900d2b..0000000000 --- a/docs/accessanalyzer/1.0/connectors/iam/localgroups/usergroupcollection.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: "Local User and Group Collection" -description: "Collecting local users and groups from target machines" -sidebar_position: 20 ---- - -# Local User and Group Collection - -The Local Groups connector collects local users, local groups, and group memberships from Windows machines via PowerShell Remoting. - -## What Gets Collected - -| Object Type | Data Collected | -| --- | --- | -| **Local users** | Username, full name, description, enabled status, last logon | -| **Local groups** | Group name, description, type | -| **Group memberships** | Local group members (local users and domain accounts/groups) | - -## Running a Sync - -1. Navigate to **Configuration** > **Scans** -2. Create or select a scan configured for the Local Groups source -3. Run the scan — the connector performs a sync on each execution - -## How It Works - -The connector: - -1. Establishes a WinRM session to the target machine -2. Executes PowerShell commands to enumerate local users and groups -3. Collects group membership information, including domain accounts that are members of local groups -4. Returns results to the Core API for storage and analysis - -## Use Cases - -Local group collection is useful for: - -- Identifying domain accounts with local administrator access -- Mapping local group memberships that grant file share permissions -- Detecting overly permissive local group configurations diff --git a/docs/accessanalyzer/1.0/connectors/iam/overview.md b/docs/accessanalyzer/1.0/connectors/iam/overview.md deleted file mode 100644 index e0f373519b..0000000000 --- a/docs/accessanalyzer/1.0/connectors/iam/overview.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: "IAM Connectors" -description: "Identity and access management connectors" -sidebar_position: 1 ---- - -# IAM Connectors - -IAM (Identity and Access Management) connectors synchronize identity data — users, groups, and group memberships — from identity providers into Access Analyzer. This data is used to map who has access to what across your data sources. - -## Available IAM Connectors - -| Connector | Identity Provider | Operations | Credential Type | -| --- | --- | --- | --- | -| [Active Directory](/docs/accessanalyzer/1_0/connectors/iam/activedirectory/connectionsetup) | On-premises AD | Test connection, Full sync | Username / Password | -| [Entra ID](/docs/accessanalyzer/1_0/connectors/iam/entraid/appregistration) | Microsoft Entra ID | Test connection only | OAuth2 Client Credentials | -| [Local Groups](/docs/accessanalyzer/1_0/connectors/iam/localgroups/powershellsetup) | Windows local accounts | Test connection, Sync | Username / Password | - -:::note -The Entra ID connector in v1.0 supports test connection only. Full identity synchronization will be available in a future release. -::: diff --git a/docs/accessanalyzer/1.0/connectors/overview.md b/docs/accessanalyzer/1.0/connectors/overview.md deleted file mode 100644 index e3c68accb8..0000000000 --- a/docs/accessanalyzer/1.0/connectors/overview.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: "Connectors" -description: "Connector architecture, types, and lifecycle" -sidebar_position: 1 ---- - -# Connectors - -Connectors are the components that communicate with external data sources and identity providers on behalf of Access Analyzer. Each connector handles authentication, data collection, and state management for its target system. - -## Connector Types - -| Category | Purpose | Connectors | -| --- | --- | --- | -| **IAM Connectors** | Synchronize identities (users, groups, memberships) from identity providers | [Active Directory](/docs/accessanalyzer/1_0/connectors/iam/activedirectory/connectionsetup), [Entra ID](/docs/accessanalyzer/1_0/connectors/iam/entraid/appregistration), [Local Groups](/docs/accessanalyzer/1_0/connectors/iam/localgroups/powershellsetup) | -| **Source Connectors** | Scan data repositories for files, permissions, and content | [CIFS/SMB](/docs/accessanalyzer/1_0/connectors/source/cifs/connectionconfig), [SharePoint Online](/docs/accessanalyzer/1_0/connectors/source/sharepointonline/connectionconfig) | - -## Connector Operations - -| Operation | Description | -| --- | --- | -| **Test connection** | Validates credentials and network connectivity | -| **Access scan** | Enumerates files, folders, and permissions on a data source | -| **Sync** | Synchronizes users, groups, and memberships from an identity provider | -| **Get object** | Retrieves specific objects or metadata from the target system | - -## Connector Execution - -Connectors run as Kubernetes Jobs managed by the Connector API. When a scan or sync is triggered: - -1. The Core API creates a scan execution record -2. The Connector API launches a Kubernetes Job with the appropriate connector -3. The connector authenticates using the associated service account -4. Data is collected and sent back to the Core API for processing -5. The job completes and reports its final status - -## State Management - -| Connector | Pause/Resume | -| --- | --- | -| CIFS/SMB | Supported | -| All others | Not supported | diff --git a/docs/accessanalyzer/1.0/connectors/source/_category_.json b/docs/accessanalyzer/1.0/connectors/source/_category_.json deleted file mode 100644 index 895acef0a9..0000000000 --- a/docs/accessanalyzer/1.0/connectors/source/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Source Connectors", - "position": 20, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/connectors/source/cifs/_category_.json b/docs/accessanalyzer/1.0/connectors/source/cifs/_category_.json deleted file mode 100644 index 6e8930174e..0000000000 --- a/docs/accessanalyzer/1.0/connectors/source/cifs/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "CIFS / SMB File Shares", - "position": 10, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "connectionconfig" - } -} diff --git a/docs/accessanalyzer/1.0/connectors/source/cifs/connectionconfig.md b/docs/accessanalyzer/1.0/connectors/source/cifs/connectionconfig.md deleted file mode 100644 index 433e9c371a..0000000000 --- a/docs/accessanalyzer/1.0/connectors/source/cifs/connectionconfig.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -title: "Connection Configuration" -description: "Configuring CIFS/SMB connection parameters" -sidebar_position: 10 ---- - -# Connection Configuration - -Configure the CIFS/SMB connector to scan Windows file shares for files, folders, and access permissions. File server sources are created through the **Connect Source** wizard, which supports adding multiple servers in a single source group. - -## Prerequisites - -- A service account with read access to target shares — see [CIFS Requirements](/docs/accessanalyzer/1_0/requirements/connectors/cifs) -- Network connectivity from Access Analyzer to each file server on port 445 - -## Creating a File Server Source Group - -File server sources are created through the 3-step **Connect Source** wizard: - -### Step 1 — Select Source Type - -1. Navigate to **Configuration** > **Sources** -2. Click **Connect Source** to open the wizard drawer -3. Select **File Server** from the source type cards -4. Click **Next** - -### Step 2 — Configure File Server - -1. Enter a **Source Group Name** (for example, `Finance File Servers`) -2. Select or create a **Service Account**: - - Click **+ Create New Account** to add a new username/password account - - Or select an existing service account from the dropdown -3. Optionally enter a **Domain** name (for example, `company.local`). The domain is applied to all servers in the group. - -### Adding File Servers - -Click **+ Add** or click the empty state area to begin adding servers: - -1. Select **Add Manually** (CSV import is planned for a future release) -2. In the manual entry form, enter one or more server names or IP addresses: - - Type multiple entries separated by commas, or press **Enter** after each one - - For example: `fs01, fs02, fs03` -3. Set the **Port** (default: `445`) -4. Click **Add [N] file servers** -5. Review the added servers in the table — server names are editable inline -6. Click **Done** to return to the configuration screen - -The file servers table shows each server's name, connection status, and a delete button. - -### Test Connection - -After adding servers and selecting a service account: - -1. Click **Test Connection** -2. All servers are tested in parallel -3. Each server shows its status: **Connected** (green), **Failed** (red), or **Testing** (spinner) -4. A summary toast displays the results (for example, "All 3 connections successful" or "1 of 3 failed") - -:::note -Testing is optional and non-blocking — you can proceed to the next step regardless of test results. -::: - -### Connection Parameters - -Each file server in the group uses the following connection parameters: - -| Parameter | Description | Default | -| --- | --- | --- | -| **Host** | File server hostname or IP address | — | -| **Port** | SMB port | `445` | -| **Domain** | Domain name (set at the group level) | — | - -## Supported Protocols - -The connector supports SMBv2 and SMBv3. SMBv1 is not supported due to security vulnerabilities. - -## Next Steps - -After configuring servers, click **Next** to proceed to [scan setup](/docs/accessanalyzer/1_0/gettingstarted/firstscan/configuringscan), where you configure access scan options, share filtering, and scheduling. diff --git a/docs/accessanalyzer/1.0/connectors/source/cifs/filevssharelevel.md b/docs/accessanalyzer/1.0/connectors/source/cifs/filevssharelevel.md deleted file mode 100644 index e3e596a606..0000000000 --- a/docs/accessanalyzer/1.0/connectors/source/cifs/filevssharelevel.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: "File-Level vs Share-Level Permissions" -description: "Understanding file-level and share-level permission scanning" -sidebar_position: 50 ---- - -# File-Level vs Share-Level Permissions - -Windows file shares have two layers of access control: **share-level permissions** and **NTFS file-level permissions**. The effective access for a user is the most restrictive combination of both. - -## Share-Level Permissions - -Share-level permissions are set on the share itself and apply to all network access: - -- **Read** — View files and subfolders -- **Change** — Read, add, modify, and delete files -- **Full Control** — All Change permissions plus the ability to modify share permissions - -## NTFS File-Level Permissions - -NTFS permissions are set on individual files and folders and provide granular control: - -- **Read** — View file contents and attributes -- **Write** — Create files and write data -- **Modify** — Read, write, and delete -- **Full Control** — All permissions including permission changes and ownership - -## Effective Access - -The effective access for a user connecting over the network is determined by the **intersection** (most restrictive) of share-level and NTFS permissions. - -For example: -- Share permission: **Full Control** -- NTFS permission: **Read** -- Effective access: **Read** - -## Enabling File-Level Permission Scanning - -By default, Access Analyzer scans share-level permissions only. To include file-level (NTFS) permission data: - -1. During source group creation, proceed to Step 3 (scan setup) -2. Enable the **Access** scan type -3. In the access scan options, check **Include file-level permission data in scan results** - -When enabled, the connector reads the NTFS security descriptor for each file and folder in addition to the share-level ACL. This provides more detailed access path analysis but increases scan duration. - -:::note -File-level permission scanning is disabled by default because it significantly increases scan time on large file servers. Enable it when you need detailed per-file permission analysis. -::: - -## What Access Analyzer Scans - -The CIFS/SMB connector collects NTFS permissions at the file and folder level. Combined with share-level permission data, Access Analyzer reports the effective access path from user to file. diff --git a/docs/accessanalyzer/1.0/connectors/source/cifs/ntfspermissions.md b/docs/accessanalyzer/1.0/connectors/source/cifs/ntfspermissions.md deleted file mode 100644 index 6b14bc1b67..0000000000 --- a/docs/accessanalyzer/1.0/connectors/source/cifs/ntfspermissions.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: "NTFS Permission Scanning" -description: "Scanning NTFS access control lists" -sidebar_position: 30 ---- - -# NTFS Permission Scanning - -The CIFS/SMB connector reads NTFS access control lists (ACLs) on files and folders to identify who has access and what level of access they hold. - -## What Gets Collected - -| Data | Description | -| --- | --- | -| **ACL entries** | Each access control entry (ACE) on a file or folder, including the principal (user or group), access type (allow/deny), and permission level | -| **Permission types** | Read, Write, Modify, Full Control, and other standard NTFS permissions | -| **Inheritance** | Whether permissions are inherited from a parent folder or explicitly set | -| **Owner** | The owner of each file or folder | - -## How It Works - -1. The connector traverses the folder hierarchy on each share -2. For each file and folder, it reads the NTFS security descriptor -3. ACL entries are parsed and stored in the Access Analyzer database -4. Identities referenced in ACLs are matched to synced identities from IAM connectors - -## Access Path Analysis - -By combining NTFS permissions with identity data from Active Directory or Local Groups, Access Analyzer builds **access paths** that show: - -- Which users and groups have access to each file or folder -- Whether access is granted directly or through nested group membership -- Which permissions are explicitly set versus inherited diff --git a/docs/accessanalyzer/1.0/connectors/source/cifs/scandepthworkers.md b/docs/accessanalyzer/1.0/connectors/source/cifs/scandepthworkers.md deleted file mode 100644 index b83787d563..0000000000 --- a/docs/accessanalyzer/1.0/connectors/source/cifs/scandepthworkers.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: "Scan Depth and Worker Configuration" -description: "Configuring recursion depth and concurrent workers" -sidebar_position: 40 ---- - -# Scan Depth and Worker Configuration - -The CIFS/SMB connector supports configurable scan depth and concurrent worker threads to balance thoroughness with performance. These settings are configured in Step 3 (scan setup) of the Connect Source wizard when the **Access** scan option is enabled. - -## Scan Depth - -Scan depth controls how many levels of subdirectories the connector traverses within each share. - -| Setting | Description | -| --- | --- | -| **Default** | 50 levels deep | -| **Custom** | Set to any positive integer | - -The default depth of 50 covers the vast majority of file server hierarchies. Increase this value only if your environment has deeply nested folder structures that exceed 50 levels. - -:::note -Setting scan depth to a very high number does not significantly impact performance if the actual folder hierarchy is shallower — the connector stops when there are no more subdirectories to traverse. -::: - -## Worker Threads - -Worker threads control how many directories are scanned concurrently. More threads mean faster scans but higher load on the file server. - -| Setting | Description | -| --- | --- | -| **Default** | 3 concurrent workers | -| **Range** | 1 to 20 workers | - -Guidelines for choosing a worker count: - -| Workers | Use Case | -| --- | --- | -| **1–3** | Conservative scanning with minimal file server impact (default) | -| **5–10** | Balanced performance for most environments | -| **10–20** | Maximum parallelism for large file servers with high I/O capacity | - -:::warning -Increasing worker count improves scan speed but also increases load on the file server. Start with the default of 3 and increase gradually based on file server capacity and observed scan duration. -::: - -## Configuration Location - -Both settings are found in the **Access scan options** section of the scan setup step, which appears when the **Access** scan type is enabled during source group creation. - -## Related Topics - -- [Share Enumeration and Filtering](/docs/accessanalyzer/1_0/connectors/source/cifs/shareenumeration) — Controlling which shares are scanned -- [File-Level vs Share-Level Permissions](/docs/accessanalyzer/1_0/connectors/source/cifs/filevssharelevel) — Permission scanning granularity diff --git a/docs/accessanalyzer/1.0/connectors/source/cifs/shareenumeration.md b/docs/accessanalyzer/1.0/connectors/source/cifs/shareenumeration.md deleted file mode 100644 index 9bcb80a771..0000000000 --- a/docs/accessanalyzer/1.0/connectors/source/cifs/shareenumeration.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: "Share Enumeration and Filtering" -description: "Discovering and filtering network shares" -sidebar_position: 20 ---- - -# Share Enumeration and Filtering - -When scanning a CIFS/SMB source, the connector discovers all available shares on the target file server. You can include or exclude specific shares, and optionally enumerate hidden shares. - -## How Share Discovery Works - -The connector enumerates all SMB shares exposed by the file server. Each share is listed with its name and path. - -## Share Filtering - -Share filtering is configured in Step 3 (scan setup) of the Connect Source wizard when the **Access** scan option is enabled. Two filtering controls are available: - -### Include Shares - -Control which shares are scanned: - -| Mode | Behavior | -| --- | --- | -| **All shares** (default) | Scan every discovered share on the file server | -| **Custom selection** | Only scan shares you explicitly specify | - -When **Custom selection** is chosen, a text field appears where you enter share names separated by commas (for example, `share1, share2, share3`). - -### Exclude Shares - -Optionally specify shares to skip during scanning. Enter share names separated by commas in the exclude field (for example, `admin$, ipc$`). Excluded shares are never scanned, even if they match the include filter. - -## Hidden Shares - -Windows hidden shares (shares whose names end with `$`) are not enumerated by default. You can enable automatic discovery of hidden shares: - -1. In the scan setup step, check **Automatically enumerate and scan hidden shares** -2. When enabled, the connector discovers and scans hidden shares alongside regular shares -3. A predefined list of default exclusions is applied automatically - -### Excluding Hidden Shares - -When hidden share collection is enabled, an additional **Exclude Hidden Shares** field appears. Enter hidden share names to exclude from auto-enumeration (for example, `ADMIN$, C$, IPC$`). - -:::info -Filtering shares reduces scan duration and focuses results on the most relevant data repositories. Exclude administrative shares (like `ADMIN$` and `IPC$`) unless you specifically need to audit their permissions. -::: - -## Related Topics - -- [Connection Configuration](/docs/accessanalyzer/1_0/connectors/source/cifs/connectionconfig) — Setting up file server connections -- [Scan Depth and Worker Configuration](/docs/accessanalyzer/1_0/connectors/source/cifs/scandepthworkers) — Controlling scan thoroughness diff --git a/docs/accessanalyzer/1.0/connectors/source/overview.md b/docs/accessanalyzer/1.0/connectors/source/overview.md deleted file mode 100644 index 90620d8484..0000000000 --- a/docs/accessanalyzer/1.0/connectors/source/overview.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: "Source Connectors" -description: "Data source connectors for file and cloud scanning" -sidebar_position: 1 ---- - -# Source Connectors - -Source connectors scan data repositories to discover files, folders, access permissions, and content. Results are used to identify overly permissive access and detect sensitive data. - -## Available Source Connectors - -| Connector | Data Source | Operations | Credential Type | -| --- | --- | --- | --- | -| [CIFS / SMB](/docs/accessanalyzer/1_0/connectors/source/cifs/connectionconfig) | Windows file shares | Test connection, Access scan, Get object | Username / Password | -| [SharePoint Online](/docs/accessanalyzer/1_0/connectors/source/sharepointonline/connectionconfig) | SharePoint Online sites | Test connection, Access scan, Get object | Certificate | - -## Scan Types - -| Scan Type | Description | -| --- | --- | -| **Access scan** | Enumerates file structure and access permissions | -| **Sensitive data scan** | Classifies file content against detection patterns | diff --git a/docs/accessanalyzer/1.0/connectors/source/sharepointonline/_category_.json b/docs/accessanalyzer/1.0/connectors/source/sharepointonline/_category_.json deleted file mode 100644 index 4646f7123f..0000000000 --- a/docs/accessanalyzer/1.0/connectors/source/sharepointonline/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "SharePoint Online", - "position": 20, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "connectionconfig" - } -} diff --git a/docs/accessanalyzer/1.0/connectors/source/sharepointonline/connectionconfig.md b/docs/accessanalyzer/1.0/connectors/source/sharepointonline/connectionconfig.md deleted file mode 100644 index 90bd541e78..0000000000 --- a/docs/accessanalyzer/1.0/connectors/source/sharepointonline/connectionconfig.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: "Connection Configuration" -description: "Configuring SharePoint Online connection parameters" -sidebar_position: 10 ---- - -# Connection Configuration - -Configure the SharePoint Online connector to scan SharePoint sites using the Microsoft Graph API with certificate-based authentication. - -## Prerequisites - -- An Azure AD app registration with `Sites.Read.All` permission — see [SharePoint Online Requirements](/docs/accessanalyzer/1_0/requirements/connectors/sharepointonline) -- A certificate (public/private key pair) uploaded to the app registration -- Network connectivity from Access Analyzer to Microsoft Graph API (port 443) - -## Create a Service Account - -1. Navigate to **Service Accounts** in the sidebar -2. Click **Add Service Account** -3. Enter a **Name** (for example, `SharePoint Online - Graph API`) -4. Select **Certificate** as the type -5. Enter the **Client ID** (Application ID from the Azure app registration) -6. Enter the **Tenant ID** (Directory ID) -7. Upload the **Certificate** (private key `.pem` file) -8. Click **Add service account** - -## Add a SharePoint Online Source - -1. Navigate to **Configuration** > **Sources** -2. Click **Add Source** -3. Select **Data Source** as the category -4. Select **SharePoint Online** as the source type -5. Select the certificate-based service account created above -6. Click **Test Connection** to verify Graph API connectivity -7. After a successful test, click **Create Source** - -## Test Connection - -The test connection validates: - -- Certificate authentication with the Microsoft identity platform -- Graph API access with the configured permissions -- Ability to enumerate SharePoint sites diff --git a/docs/accessanalyzer/1.0/connectors/source/sharepointonline/permissionsharinglinks.md b/docs/accessanalyzer/1.0/connectors/source/sharepointonline/permissionsharinglinks.md deleted file mode 100644 index 18a311c439..0000000000 --- a/docs/accessanalyzer/1.0/connectors/source/sharepointonline/permissionsharinglinks.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: "Permission and Sharing Link Analysis" -description: "Analyzing SharePoint permissions and external sharing links" -sidebar_position: 30 ---- - -# Permission and Sharing Link Analysis - -The SharePoint Online connector collects permission data from SharePoint sites to identify who has access to documents and whether content is shared externally. - -## What Gets Collected - -| Data | Description | -| --- | --- | -| **Site permissions** | Users and groups with access to the site, including permission levels (Full Control, Edit, Read) | -| **Library permissions** | Custom permissions set at the document library level | -| **Item-level permissions** | Unique permissions on individual files or folders (broken inheritance) | -| **Sharing links** | Anonymous links, organization-wide links, and people-specific sharing links | - -## Sharing Link Types - -| Link Type | Description | Risk Level | -| --- | --- | --- | -| **Anyone** | Anonymous access — no authentication required | High | -| **Organization** | Anyone in the organization can access | Medium | -| **Specific people** | Only named users can access | Low | - -## How It Helps - -Permission and sharing link analysis enables you to: - -- Identify documents shared externally via anonymous links -- Find overly permissive site-level access -- Detect broken permission inheritance on sensitive documents -- Review sharing link expiration and access levels diff --git a/docs/accessanalyzer/1.0/connectors/source/sharepointonline/scanningspecificsites.md b/docs/accessanalyzer/1.0/connectors/source/sharepointonline/scanningspecificsites.md deleted file mode 100644 index e4203c5679..0000000000 --- a/docs/accessanalyzer/1.0/connectors/source/sharepointonline/scanningspecificsites.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: "Scanning Specific Sites" -description: "Targeting specific SharePoint sites for scanning" -sidebar_position: 40 ---- - -# Scanning Specific Sites - -By default, the SharePoint Online connector scans all sites accessible to the configured app registration. You can narrow the scope by including or excluding specific sites. - -## Configuring Site Filters - -Site filtering is configured during scan creation in the **Configure Details** step: - -1. Navigate to **Configuration** > **Scans** -2. Create a new scan for the SharePoint Online source -3. In the **Configure Details** step, set site include or exclude filters - -## Filter Options - -| Option | Behavior | -| --- | --- | -| **Include specific sites** | Only scan the listed sites | -| **Exclude specific sites** | Scan all sites except those listed | - -## Use Cases - -- **Compliance scanning** — Scan only sites that contain regulated data (HR, Finance, Legal) -- **Incremental rollout** — Start with a subset of sites and expand over time -- **Performance** — Reduce scan duration by excluding large, low-priority sites diff --git a/docs/accessanalyzer/1.0/connectors/source/sharepointonline/sitelibraryenum.md b/docs/accessanalyzer/1.0/connectors/source/sharepointonline/sitelibraryenum.md deleted file mode 100644 index 62a46f11d3..0000000000 --- a/docs/accessanalyzer/1.0/connectors/source/sharepointonline/sitelibraryenum.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: "Site and Library Enumeration" -description: "Discovering SharePoint sites and document libraries" -sidebar_position: 20 ---- - -# Site and Library Enumeration - -The SharePoint Online connector discovers SharePoint sites, document libraries, and their contents through the Microsoft Graph API. - -## What Gets Discovered - -| Object Type | Description | -| --- | --- | -| **Sites** | All SharePoint Online sites accessible to the app registration | -| **Document libraries** | Libraries within each site containing files and folders | -| **Files and folders** | Individual items with metadata (name, size, modified date, author) | - -## How It Works - -1. The connector authenticates with the Graph API using the configured certificate -2. Sites are enumerated based on the app registration's permissions (`Sites.Read.All`) -3. For each site, document libraries are discovered -4. Files and folders within each library are traversed and cataloged -5. Results are sent to the Core API for storage and analysis - -## Site Filtering - -You can control which sites are scanned using include/exclude filters. See [Scanning Specific Sites](/docs/accessanalyzer/1_0/connectors/source/sharepointonline/scanningspecificsites) for details. diff --git a/docs/accessanalyzer/1.0/dashboards/_category_.json b/docs/accessanalyzer/1.0/dashboards/_category_.json deleted file mode 100644 index 4795b98214..0000000000 --- a/docs/accessanalyzer/1.0/dashboards/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Dashboards and Reports", - "position": 80, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/dashboards/activedirectory.md b/docs/accessanalyzer/1.0/dashboards/activedirectory.md deleted file mode 100644 index 0a72e8f46e..0000000000 --- a/docs/accessanalyzer/1.0/dashboards/activedirectory.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Active Directory Dashboard" -description: "Active Directory identity and access insights" -sidebar_position: 20 -draft: true ---- - -# Active Directory Dashboard diff --git a/docs/accessanalyzer/1.0/dashboards/copilotreadiness.md b/docs/accessanalyzer/1.0/dashboards/copilotreadiness.md deleted file mode 100644 index ea7b3647a0..0000000000 --- a/docs/accessanalyzer/1.0/dashboards/copilotreadiness.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Copilot Readiness Dashboard" -description: "Microsoft 365 Copilot readiness assessment" -sidebar_position: 50 -draft: true ---- - -# Copilot Readiness Dashboard diff --git a/docs/accessanalyzer/1.0/dashboards/datasecurity.md b/docs/accessanalyzer/1.0/dashboards/datasecurity.md deleted file mode 100644 index a9db5d2e47..0000000000 --- a/docs/accessanalyzer/1.0/dashboards/datasecurity.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Data Security Dashboard" -description: "Data security posture and risk summary" -sidebar_position: 40 -draft: true ---- - -# Data Security Dashboard diff --git a/docs/accessanalyzer/1.0/dashboards/entraid.md b/docs/accessanalyzer/1.0/dashboards/entraid.md deleted file mode 100644 index c2f2ebf0c2..0000000000 --- a/docs/accessanalyzer/1.0/dashboards/entraid.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Entra ID Dashboard" -description: "Entra ID identity and access insights" -sidebar_position: 30 -draft: true ---- - -# Entra ID Dashboard diff --git a/docs/accessanalyzer/1.0/dashboards/metabase/_category_.json b/docs/accessanalyzer/1.0/dashboards/metabase/_category_.json deleted file mode 100644 index af130ea1f5..0000000000 --- a/docs/accessanalyzer/1.0/dashboards/metabase/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Metabase Reports", - "position": 60, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "accessingreports" - } -} diff --git a/docs/accessanalyzer/1.0/dashboards/metabase/accessingreports.md b/docs/accessanalyzer/1.0/dashboards/metabase/accessingreports.md deleted file mode 100644 index c9919abbcc..0000000000 --- a/docs/accessanalyzer/1.0/dashboards/metabase/accessingreports.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: "Accessing Embedded Reports" -description: "Using Metabase embedded reports in Access Analyzer" -sidebar_position: 10 ---- - -# Accessing Embedded Reports - -Access Analyzer embeds Metabase reports directly into the application interface. You can view, filter, and interact with reports without leaving the platform. - -## Opening a Report - -1. Navigate to the **Dashboards** section in the left navigation menu. -2. Select a dashboard from the list of available dashboards (for example, **Data Security Dashboard**). -3. The embedded Metabase report loads within the Access Analyzer interface. - -## Authentication - -Report access uses JWT-based single sign-on between the Access Analyzer Core API and Metabase. No separate Metabase credentials are required. Your Access Analyzer user permissions determine which dashboards and data you can view. - -## Interacting with Reports - -Once a report is loaded, you can: - -- **Apply filters** — Use the filter controls at the top of the dashboard to narrow results by date range, data source, compliance framework, or data type. -- **Drill down** — Click on chart elements or table rows to view detailed breakdowns of the underlying data. -- **Adjust time ranges** — Modify the reporting period to compare findings across different scan windows. - -:::note -Dashboards display data from the most recent completed scans. If you do not see expected results, verify that a [sensitive data scan](/docs/accessanalyzer/1_0/sensitivedatadiscovery/runningscan) has been run against the target data sources. -::: - -## Next Steps - -- [Save reports](/docs/accessanalyzer/1_0/dashboards/metabase/savedreports) for repeated access -- [Export report data](/docs/accessanalyzer/1_0/dashboards/metabase/exportingdata) for external use diff --git a/docs/accessanalyzer/1.0/dashboards/metabase/exportingdata.md b/docs/accessanalyzer/1.0/dashboards/metabase/exportingdata.md deleted file mode 100644 index 9b8531c8e7..0000000000 --- a/docs/accessanalyzer/1.0/dashboards/metabase/exportingdata.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: "Exporting Report Data" -description: "Exporting report data for external use" -sidebar_position: 30 ---- - -# Exporting Report Data - -Access Analyzer allows you to export dashboard data from embedded Metabase reports for use in external tools, compliance documentation, or offline analysis. - -## Exporting from a Dashboard - -To export data from a dashboard or saved report: - -1. Open the desired dashboard or [saved report](/docs/accessanalyzer/1_0/dashboards/metabase/savedreports). -2. Apply any filters to scope the data to your requirements. -3. Click the **Export** button in the dashboard toolbar. -4. Select the export format: - - **CSV** — Comma-separated values for use in spreadsheets and data processing tools - - **JSON** — Structured data format for programmatic consumption - - **PDF** — Formatted report suitable for distribution and compliance documentation -5. Click **Download** to save the exported file. - -## Export Scope - -The exported data reflects the current dashboard view, including all applied filters. Only the data visible in the current report configuration is included in the export. - -| Export Format | Best For | -| --- | --- | -| CSV | Importing into Excel, Google Sheets, or data analysis tools | -| JSON | Integration with APIs, scripts, or automated reporting pipelines | -| PDF | Sharing with stakeholders, auditors, or compliance teams | - -:::warning -Exported reports may contain sensitive data findings. Handle exported files according to your organization's data handling and classification policies. -::: - -## Next Steps - -- [Configure saved reports](/docs/accessanalyzer/1_0/dashboards/metabase/savedreports) to streamline recurring exports -- [Review sensitive data scan results](/docs/accessanalyzer/1_0/sensitivedatadiscovery/reviewingresults/matchcounts) for detailed match-level data diff --git a/docs/accessanalyzer/1.0/dashboards/metabase/savedreports.md b/docs/accessanalyzer/1.0/dashboards/metabase/savedreports.md deleted file mode 100644 index 8d565d14fe..0000000000 --- a/docs/accessanalyzer/1.0/dashboards/metabase/savedreports.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: "Saved Reports" -description: "Creating and managing saved reports" -sidebar_position: 20 ---- - -# Saved Reports - -The saved reports feature allows you to preserve specific dashboard configurations, including applied filters and selected parameters, for quick access in future sessions. - -## Saving a Report - -1. Open a dashboard and apply the desired filters (date range, data source, compliance framework, or other parameters). -2. Click the **Save Report** button in the dashboard toolbar. -3. Enter a **Name** for the saved report. -4. Optionally add a **Description** to document the report's purpose. -5. Click **Save**. - -The saved report appears in your **Saved Reports** list for future access. - -## Managing Saved Reports - -To view and manage your saved reports: - -1. Navigate to **Dashboards** > **Saved Reports**. -2. The list displays all saved reports with their name, description, and creation date. -3. Click a saved report to load it with the preserved filter configuration. -4. To update a saved report, modify the filters and click **Save Report** again, then choose to overwrite the existing report. -5. To delete a saved report, select it and click **Delete**. - -:::note -Saved reports retain the filter configuration, not a static snapshot of the data. When you open a saved report, the dashboard applies the saved filters against the latest scan data, ensuring results are always current. -::: - -## Next Steps - -- [Export report data](/docs/accessanalyzer/1_0/dashboards/metabase/exportingdata) from a saved report configuration -- [Return to the dashboards overview](/docs/accessanalyzer/1_0/dashboards/overview) to explore other reporting options diff --git a/docs/accessanalyzer/1.0/dashboards/overview.md b/docs/accessanalyzer/1.0/dashboards/overview.md deleted file mode 100644 index d996ab6f5f..0000000000 --- a/docs/accessanalyzer/1.0/dashboards/overview.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: "Dashboards and Reports" -description: "Overview of dashboards, metrics, and reporting capabilities" -sidebar_position: 10 ---- - -# Dashboards and Reports - -Netwrix Access Analyzer provides embedded analytics dashboards powered by Metabase. The **Dashboards** section gives you visual insight into your organization's data security posture, sensitive data findings, and access risk summaries. - -## Embedded Analytics - -Access Analyzer integrates Metabase as an embedded reporting engine with an airgap premium token. Authentication is handled automatically through JWT-based single sign-on from the Core API to Metabase, so users access dashboards directly from within the Access Analyzer interface without separate login credentials. - -## Available Dashboards - -Pre-built dashboards are visible in the **Dashboards** section of the application. The primary dashboard is the **Data Security Dashboard**, which provides: - -- **Sensitive data findings summary** — Aggregated match counts across all scanned sources -- **Risk summary** — High-level view of data exposure organized by severity and compliance framework -- **Trend analysis** — Changes in sensitive data findings over time - -## Reporting Capabilities - -| Feature | Description | -| --- | --- | -| [Accessing Reports](/docs/accessanalyzer/1_0/dashboards/metabase/accessingreports) | View and interact with embedded Metabase reports | -| [Saved Reports](/docs/accessanalyzer/1_0/dashboards/metabase/savedreports) | Save report configurations for repeated use | -| [Exporting Data](/docs/accessanalyzer/1_0/dashboards/metabase/exportingdata) | Export dashboard data for external analysis or compliance documentation | - -:::note -Dashboard content updates automatically as new scan results become available. Run a [sensitive data scan](/docs/accessanalyzer/1_0/sensitivedatadiscovery/runningscan) to populate dashboards with the latest findings. -::: diff --git a/docs/accessanalyzer/1.0/gettingstarted/_category_.json b/docs/accessanalyzer/1.0/gettingstarted/_category_.json deleted file mode 100644 index c8341a5bc3..0000000000 --- a/docs/accessanalyzer/1.0/gettingstarted/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Getting Started", - "position": 20, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/gettingstarted/dashboardwalkthrough.md b/docs/accessanalyzer/1.0/gettingstarted/dashboardwalkthrough.md deleted file mode 100644 index 1416847ba0..0000000000 --- a/docs/accessanalyzer/1.0/gettingstarted/dashboardwalkthrough.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: "Overview Dashboard Walkthrough" -description: "Navigating the main dashboard and key metrics" -sidebar_position: 30 ---- - -# Overview Dashboard Walkthrough - -After signing in, Access Analyzer displays the main interface with a sidebar navigation menu and a central content area. This page introduces the key areas of the application. - -## Sidebar Navigation - -The sidebar provides access to all major sections: - -| Section | Description | -| --- | --- | -| **Dashboards** | Pre-built Metabase dashboards for data security posture and identity analysis | -| **Reports** | Access, content, activity, and sensitive data reports | -| **Configuration** | Sources, scans, scan executions, and sensitive data settings | -| **Service Accounts** | Manage credentials used to connect to data sources | -| **Administration** | User management and system logs (administrator only) | -| **Settings** | Application-wide settings | - -## Dashboards - -The **Dashboards** section contains embedded Metabase dashboards that provide a visual summary of your environment: - -- **Data Security Dashboard** — Overview of sensitive data findings, file statistics, and framework coverage -- Additional dashboards become available as you add data sources and run scans - -Dashboards update automatically after each scan execution. - -## Configuration Section - -The **Configuration** section is where most of the day-to-day work happens: - -- **Sources** — Add and manage the data sources and identity providers Access Analyzer connects to -- **Scans** — Create, schedule, and manage access scans and sensitive data scans -- **Scan Executions** — View the history of scan runs, including status, duration, and progress -- **Sensitive Data** — Configure the detection frameworks and patterns used during sensitive data scans - -## Next Steps - -- [Your First Scan](/docs/accessanalyzer/1_0/gettingstarted/firstscan/overview) — Follow the step-by-step guide to add a source, configure a scan, and review results diff --git a/docs/accessanalyzer/1.0/gettingstarted/firstlogin.md b/docs/accessanalyzer/1.0/gettingstarted/firstlogin.md deleted file mode 100644 index defd35ef14..0000000000 --- a/docs/accessanalyzer/1.0/gettingstarted/firstlogin.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: "First Login and Admin Setup" -description: "Initial administrator account creation and login" -sidebar_position: 20 ---- - -# First Login and Admin Setup - -After installing Access Analyzer, the first step is to access the web interface, create your administrator account, and sign in. - -## Access the Application - -Open a browser and navigate to: - -``` -https:// -``` - -Replace `` with the IP address or hostname of the VM where Access Analyzer is installed. - -:::note -Access Analyzer uses a self-signed TLS certificate by default. Your browser will display a security warning — accept the warning to proceed to the login page. To use a trusted certificate, see [SSL / TLS Configuration](/docs/accessanalyzer/1_0/install/ssl). -::: - -## Create the Administrator Account - -The first user to create an account is automatically assigned the **Administrator** role. - -1. On the login page, click **Create Account** -2. Enter the following: - - **Full Name** — Your display name - - **Email Address** — Used as your login username - - **Password** — Must meet complexity requirements - - **Confirm Password** — Re-enter the password -3. Click **Create Account** - -:::warning -The first account created receives full administrator privileges. Ensure this account is created by an authorized administrator. -::: - -## Sign In - -1. Enter the email address and password you used during account creation -2. Click **Sign In** - -You are now signed in with full administrator access. - -## Next Steps - -- [Overview Dashboard Walkthrough](/docs/accessanalyzer/1_0/gettingstarted/dashboardwalkthrough) — Explore the main interface -- [Your First Scan](/docs/accessanalyzer/1_0/gettingstarted/firstscan/overview) — Add a data source and run your first scan -- [Users and Roles](/docs/accessanalyzer/1_0/admin/users/overview) — Create additional user accounts diff --git a/docs/accessanalyzer/1.0/gettingstarted/firstscan/_category_.json b/docs/accessanalyzer/1.0/gettingstarted/firstscan/_category_.json deleted file mode 100644 index d8feb251f3..0000000000 --- a/docs/accessanalyzer/1.0/gettingstarted/firstscan/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Your First Scan", - "position": 30, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/gettingstarted/firstscan/addingsource.md b/docs/accessanalyzer/1.0/gettingstarted/firstscan/addingsource.md deleted file mode 100644 index b37b596118..0000000000 --- a/docs/accessanalyzer/1.0/gettingstarted/firstscan/addingsource.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: "Adding a Data Source" -description: "Connect a data source using the Connect Source wizard" -sidebar_position: 20 ---- - -# Adding a Data Source - -Before scanning, you need to connect a data source to Access Analyzer. The **Connect Source** wizard guides you through a 3-step process: select the source type, configure the connection, and set up a scan. - -## Open the Connect Source Wizard - -1. Navigate to **Configuration** > **Sources** in the sidebar -2. Click **Connect Source** to open the wizard drawer - -## Step 1 — Select Source Type - -Choose the type of data source to connect: - -| Source Type | Category | Description | -| --- | --- | --- | -| **Active Directory** | IAM | Domain controllers, users, groups, and permissions | -| **Entra ID** | IAM | Azure AD tenant with users, groups, and roles | -| **File Server** | Data Source | Windows file shares (CIFS/SMB) | -| **SharePoint Online** | Data Source | SharePoint sites and document libraries | - -Select a source type card and click **Next**. - -## Step 2 — Configure the Source - -Configuration varies by source type. For this getting started guide, we'll walk through the **File Server** example — the most common first source. - -### File Server Configuration - -1. Enter a **Source Group Name** (for example, `Finance File Servers`) -2. Select or create a **Service Account**: - - Click **+ Create New Account** to add credentials inline - - Select **Username/Password** and enter the username and password for an account with read access to the target file servers - - Or select an existing service account from the dropdown -3. Optionally enter a **Domain** name (for example, `company.local`) - -### Add File Servers - -1. Click **+ Add** or the empty state area -2. Select **Add Manually** -3. Enter one or more server names or IP addresses, separated by commas or pressing **Enter** after each -4. Set the **Port** (default: `445`) -5. Click **Add file servers**, then click **Done** - -### Test Connection (Optional) - -Click **Test Connection** to verify connectivity to all servers. Each server shows its connection status (Connected, Failed, or Testing). Testing is non-blocking — you can proceed regardless of results. - -:::note -If a connection test fails, verify network connectivity on port 445 and that the service account has read access to the target shares. -::: - -Click **Next** to proceed to scan setup. - -### Other Source Types - -For detailed configuration instructions for each source type, see: - -- [Active Directory](/docs/accessanalyzer/1_0/connectors/iam/activedirectory/connectionsetup) — Domain controller configuration -- [Entra ID](/docs/accessanalyzer/1_0/connectors/iam/entraid/appregistration) — Azure AD app registration and tenant setup -- [SharePoint Online](/docs/accessanalyzer/1_0/connectors/source/sharepointonline/connectionconfig) — Site collection configuration - -## Next Step - -[Configuring a Scan](/docs/accessanalyzer/1_0/gettingstarted/firstscan/configuringscan) — Set up scanning options and schedule your first scan. diff --git a/docs/accessanalyzer/1.0/gettingstarted/firstscan/configuringscan.md b/docs/accessanalyzer/1.0/gettingstarted/firstscan/configuringscan.md deleted file mode 100644 index 14df574f12..0000000000 --- a/docs/accessanalyzer/1.0/gettingstarted/firstscan/configuringscan.md +++ /dev/null @@ -1,94 +0,0 @@ ---- -title: "Configuring a Scan" -description: "Set up scanning options and schedule in the Connect Source wizard" -sidebar_position: 30 ---- - -# Configuring a Scan - -Step 3 of the Connect Source wizard configures what to scan and when. The available options depend on the source type selected in Step 1. - -## Available Scanning Options - -Select which scan types to enable for the source group. Available options vary by source type: - -### File Server Scan Types - -| Scan Type | Description | -| --- | --- | -| **Access** | Scan file server permissions and access controls | -| **Sensitive Data** | Scan file contents for sensitive data patterns (PII, credentials, PHI, financial data) | - -At least one scan type must be enabled to proceed. - -:::info -When the **Access** scan is enabled, a **Local Users and Groups** scan is also created automatically to collect local account data from each file server. This happens behind the scenes and does not require additional configuration. -::: - -### Entra ID Scan Types - -| Scan Type | Description | -| --- | --- | -| **Users, Groups and Roles** | Synchronize users, groups, and directory roles from the Azure AD tenant | - -This scan type is always enabled and cannot be disabled. Additional sync options (such as **Sync Sensitivity Labels**) may appear below the toggle. - -### Active Directory Scan Types - -| Scan Type | Description | -| --- | --- | -| **Active Directory Inventory** | Synchronize users, groups, OUs, and permissions from domain controllers | - -## Access Scan Options (File Server) - -When the **Access** scan type is enabled for a File Server source, additional configuration options appear: - -### Share Selection - -- **Include Shares** — Choose **All shares** (default) or **Custom selection** to specify specific share names -- **Exclude Shares** — Optionally list shares to skip (for example, `admin$, ipc$`) - -### Scan Depth - -- Maximum folder depth to scan (default: **50**) -- Controls how many levels of subdirectories the connector traverses - -### File-Level Permissions - -- Check **Include file-level permission data in scan results** to collect NTFS ACLs on individual files -- Disabled by default — increases scan duration on large file servers - -### Hidden Shares - -- Check **Automatically enumerate and scan hidden shares** to discover shares ending with `$` -- When enabled, an **Exclude Hidden Shares** field appears to specify hidden shares to skip (for example, `ADMIN$, C$, IPC$`) - -### Worker Threads - -- Number of concurrent workers for parallel directory enumeration (default: **3**) -- Higher values scan faster but increase load on the file server - -For detailed information about each option, see the [CIFS connector documentation](/docs/accessanalyzer/1_0/connectors/source/cifs/connectionconfig). - -## Scan Start Time - -Choose when to run the first scan: - -| Option | Description | -| --- | --- | -| **Run scan now** | Execute immediately after setup completes (default) | -| **Run scan at** | Schedule for a specific date and time — must be in the future | -| **Advanced scheduling** | Configure a recurring schedule using a cron expression | - -## Complete Setup - -Click **Complete Setup** to create the source group with all configured sources and scans. On success: - -1. The source group and all sources are created -2. Scans are created according to your configuration -3. The wizard closes and the sources list refreshes -4. Scans execute according to the selected schedule - -## Next Step - -[Running and Monitoring a Scan](/docs/accessanalyzer/1_0/gettingstarted/firstscan/runningscan) — Track scan progress and review results. diff --git a/docs/accessanalyzer/1.0/gettingstarted/firstscan/overview.md b/docs/accessanalyzer/1.0/gettingstarted/firstscan/overview.md deleted file mode 100644 index 9d968a68bd..0000000000 --- a/docs/accessanalyzer/1.0/gettingstarted/firstscan/overview.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: "Your First Scan" -description: "Step-by-step guide to running your first scan" -sidebar_position: 10 ---- - -# Your First Scan - -This guide walks you through the complete workflow of adding a data source, creating a scan, running it, and reviewing the results. The example uses a CIFS/SMB file share, but the workflow is similar for all source types. - -## Workflow Summary - -| Step | Description | Page | -| --- | --- | --- | -| 1 | Create a service account with credentials for your data source | [Adding a Data Source](/docs/accessanalyzer/1_0/gettingstarted/firstscan/addingsource) | -| 2 | Add a data source and test the connection | [Adding a Data Source](/docs/accessanalyzer/1_0/gettingstarted/firstscan/addingsource) | -| 3 | Create a scan and select scan type | [Configuring a Scan](/docs/accessanalyzer/1_0/gettingstarted/firstscan/configuringscan) | -| 4 | Run the scan and monitor progress | [Running and Monitoring a Scan](/docs/accessanalyzer/1_0/gettingstarted/firstscan/runningscan) | -| 5 | Review findings in dashboards and scan results | [Viewing Results](/docs/accessanalyzer/1_0/gettingstarted/firstscan/viewingresults) | - -## Prerequisites - -Before starting, ensure you have: - -- Signed in as an administrator — see [First Login](/docs/accessanalyzer/1_0/gettingstarted/firstlogin) -- A data source available on the network (for example, a CIFS/SMB file share) -- Credentials with read access to the data source -- Network connectivity from the Access Analyzer VM to the data source (for example, port 445 for SMB) diff --git a/docs/accessanalyzer/1.0/gettingstarted/firstscan/runningscan.md b/docs/accessanalyzer/1.0/gettingstarted/firstscan/runningscan.md deleted file mode 100644 index 9d9f001798..0000000000 --- a/docs/accessanalyzer/1.0/gettingstarted/firstscan/runningscan.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: "Running and Monitoring a Scan" -description: "Execute a scan and monitor its progress" -sidebar_position: 40 ---- - -# Running and Monitoring a Scan - -Once a scan is created, you can run it immediately or let it execute on its configured schedule. - -## Running a Scan - -There are two ways to start a scan: - -- **From the scan creation wizard** — Select **Create & Run Immediately** in the final step -- **From the Scans list** — Navigate to **Configuration** > **Scans**, click the menu button on the scan row, and select **Run** - -## Monitoring Scan Progress - -Navigate to **Configuration** > **Scan Executions** to view all scan runs. - -Each execution displays: - -| Field | Description | -| --- | --- | -| **Scan Name** | The name of the scan | -| **Scan Type** | Access or Sensitive Data | -| **Source** | The data source being scanned | -| **Status** | Running, Completed, Failed, or Paused | -| **Start Time** | When the scan execution began | -| **Duration** | Elapsed time since the scan started | - -You can filter executions by scan type, source, status, date range, and duration. - -## Scan Execution Actions - -While a scan is running, the following actions are available from the execution row menu: - -| Action | Description | -| --- | --- | -| **Stop** | Cancel the running scan | -| **Pause** | Pause the scan (CIFS/SMB sources only) | -| **Resume** | Resume a paused scan (CIFS/SMB sources only) | - -## Scan Statuses - -| Status | Meaning | -| --- | --- | -| **Running** | Scan is actively processing | -| **Completed** | Scan finished successfully | -| **Failed** | Scan encountered an error — check the execution logs | -| **Paused** | Scan has been paused and can be resumed | - -## Next Step - -[Viewing Results](/docs/accessanalyzer/1_0/gettingstarted/firstscan/viewingresults) — Review the findings from your completed scan. diff --git a/docs/accessanalyzer/1.0/gettingstarted/firstscan/viewingresults.md b/docs/accessanalyzer/1.0/gettingstarted/firstscan/viewingresults.md deleted file mode 100644 index f41a7de471..0000000000 --- a/docs/accessanalyzer/1.0/gettingstarted/firstscan/viewingresults.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: "Viewing Results" -description: "Review scan results and findings" -sidebar_position: 50 ---- - -# Viewing Results - -After a scan completes, results are available in the dashboards and reports sections. - -## Data Security Dashboard - -Navigate to **Dashboards** > **Data Security Dashboard** to view a summary of findings from your scans. The dashboard provides visualizations for: - -- Sensitive data findings by type and compliance framework -- File and data statistics -- Data exposure and risk indicators - -The dashboard updates automatically after each scan execution completes. - -## Scan Execution Details - -For per-scan results, navigate to **Configuration** > **Scan Executions**: - -1. Find the completed scan execution in the list -2. Click on the execution to view detailed results -3. Review the findings, including: - - Files and folders analyzed - - Permissions and access paths discovered - - Sensitive data matches (for sensitive data scans) - -## Reports - -Access Analyzer provides several report categories accessible from the sidebar: - -| Report Type | Description | -| --- | --- | -| **Access Reports** | Permission analysis and access path details | -| **Content Reports** | File and folder inventory statistics | -| **Sensitive Data Reports** | Sensitive data findings by category and compliance framework | - -## What's Next - -Now that you have completed your first scan and reviewed the results, consider these next steps: - -- **Add more data sources** — Connect additional file shares, SharePoint sites, or identity providers. See [Connectors](/docs/accessanalyzer/1_0/connectors/overview). -- **Configure sensitive data detection** — Customize detection patterns and taxonomy groups. See [Sensitive Data Discovery](/docs/accessanalyzer/1_0/sensitivedatadiscovery/overview). -- **Schedule recurring scans** — Set up automated scan schedules to maintain continuous visibility. See [Scans](/docs/accessanalyzer/1_0/admin/scans/overview). -- **Create additional users** — Add team members with appropriate roles. See [Users and Roles](/docs/accessanalyzer/1_0/admin/users/overview). diff --git a/docs/accessanalyzer/1.0/gettingstarted/overview.md b/docs/accessanalyzer/1.0/gettingstarted/overview.md deleted file mode 100644 index bb9c6c66f8..0000000000 --- a/docs/accessanalyzer/1.0/gettingstarted/overview.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: "Getting Started" -description: "Get up and running with Access Analyzer" -sidebar_position: 10 ---- - -# Getting Started - -This section walks you through the initial setup steps after installing Access Analyzer, from your first login to running your first scan and reviewing results. - -## Getting Started Steps - -| Step | Description | Page | -| --- | --- | --- | -| 1 | Sign in and create your administrator account | [First Login and Admin Setup](/docs/accessanalyzer/1_0/gettingstarted/firstlogin) | -| 2 | Explore the main dashboard and navigation | [Overview Dashboard Walkthrough](/docs/accessanalyzer/1_0/gettingstarted/dashboardwalkthrough) | -| 3 | Add a data source, configure a scan, and view results | [Your First Scan](/docs/accessanalyzer/1_0/gettingstarted/firstscan/overview) | - -## Prerequisites - -Before starting this guide, ensure you have: - -- Completed the [installation](/docs/accessanalyzer/1_0/install/overview) of Access Analyzer -- Verified that all services are healthy — see [Post-Installation Validation](/docs/accessanalyzer/1_0/install/postinstall) -- Network connectivity from the Access Analyzer VM to the data sources you plan to scan -- Credentials (service account) for the data sources you want to connect diff --git a/docs/accessanalyzer/1.0/index.md b/docs/accessanalyzer/1.0/index.md index ee95583019..854bbb7dbe 100644 --- a/docs/accessanalyzer/1.0/index.md +++ b/docs/accessanalyzer/1.0/index.md @@ -1,30 +1,20 @@ --- title: "Netwrix Access Analyzer Documentation" -description: "Netwrix Access Analyzer 1.0 product documentation - installation, administration, connectors, and sensitive data discovery" +description: "Netwrix Access Analyzer 1.0 product documentation - on-premises DSPM platform for data security and access analysis" sidebar_position: 1 --- # Netwrix Access Analyzer Documentation -Netwrix Access Analyzer is a cloud-native Data Security Posture Management (DSPM) platform that helps organizations discover, classify, and monitor sensitive data across enterprise systems and cloud storage. It provides comprehensive visibility into data access patterns, identifies compliance risks, and enables data governance at scale. +Netwrix Access Analyzer is an on-premises Data Security Posture Management (DSPM) platform that helps organizations discover, classify, and monitor sensitive data across enterprise file systems. Deployed entirely within your own infrastructure, it provides comprehensive visibility into data access patterns, identifies compliance risks, and enables data governance — without sending data to the cloud. ## Key Capabilities -- **Data Source Scanning** — Connect to CIFS/SMB file shares, SharePoint Online, and more to discover and analyze data +- **Data Source Scanning** — Connect to CIFS/SMB file shares and other on-premises data repositories to discover and analyze data - **Sensitive Data Discovery** — Detect sensitive data using built-in and custom regex patterns with taxonomy-based classification - **Identity and Access Management** — Sync users and groups from Active Directory and Entra ID to analyze permission paths -- **Activity Monitoring** — Track file access and user activity via Netwrix Activity Monitor integration - **Dashboards and Reporting** — Visualize security posture with built-in dashboards and embedded Metabase reports ## Documentation Sections -- [Overview](overview/overview) — Architecture, components, and key concepts -- [Getting Started](gettingstarted/overview) — First login, dashboard walkthrough, and your first scan -- [Requirements](requirements/overview) — System, database, and connector prerequisites -- [Installation](install/overview) — Kubernetes deployment, infrastructure setup, and database initialization -- [Administration](admin/overview) — User management, sources, scans, and application settings -- [Connectors](connectors/overview) — IAM and source connector configuration -- [Sensitive Data Discovery](sensitivedatadiscovery/overview) — Patterns, taxonomy, classification, and scan results -- [Dashboards and Reports](dashboards/overview) — Built-in dashboards and Metabase reporting -- [Activity Monitoring](activitymonitoring/overview) — Syslog integration with Netwrix Activity Monitor -- [Monitoring and Troubleshooting](troubleshooting/overview) — Health checks, observability, and common issues +- [Overview](overview/overview) — Introduction to the product, key concepts, requirements, and installation diff --git a/docs/accessanalyzer/1.0/overview/architecture.md b/docs/accessanalyzer/1.0/overview/architecture.md deleted file mode 100644 index 56014309b5..0000000000 --- a/docs/accessanalyzer/1.0/overview/architecture.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -title: "Architecture Overview" -description: "Core components and how they work together" -sidebar_position: 20 ---- - -# Architecture Overview - -Access Analyzer runs as a set of containerized services on a single-node Kubernetes cluster (K3s), managed by ArgoCD for automated deployment and updates. - -## Component Architecture - -| Component | Technology | Purpose | -| --- | --- | --- | -| **Core API** | Ruby on Rails 8 | Business logic, REST API, session management | -| **Web Application** | React 18, TypeScript | User interface and dashboards | -| **Connector API** | Go | Manages connector execution as Kubernetes Jobs | -| **PostgreSQL** | v14.18 | Primary relational database for configuration and scan metadata | -| **ClickHouse** | v25.8.13 | Analytics database for scan results, logs, and traces | -| **Redis** | v8.4.0 | Session storage, job queues, and caching | -| **Metabase** | Embedded (airgap) | Dashboard and reporting engine | -| **Traefik** | Ingress controller | TLS termination and request routing | -| **ArgoCD** | v3.2.0 | GitOps-based application lifecycle management | -| **K3s** | v1.33.4 | Lightweight Kubernetes distribution | -| **OpenTelemetry** | Collector | Observability data pipeline (traces and logs) | -| **Prometheus** | v3.8.0 | Metrics collection and alerting | - -## Communication Flow - -Access Analyzer operates in three phases: - -### Phase 1 — Installation - -The installer deploys K3s and ArgoCD on the target VM. ArgoCD connects to the Netwrix OCI registry to pull application Helm charts. - -### Phase 2 — Application Sync - -ArgoCD deploys applications in ordered sync waves: - -| Wave | Components | -| --- | --- | -| **Wave -5** | Secrets initialization (auto-generated database passwords, API keys) | -| **Wave 1** | Infrastructure: PostgreSQL, ClickHouse, Redis, OpenTelemetry, Prometheus, Traefik | -| **Wave 2** | Core services: Core API, Web Application, Connector API, Metabase | -| **Wave 3** | Functions and database seeds | - -### Phase 3 — Ongoing Operations - -- **Traefik** routes incoming requests: `/api/` → Core API, `/metabase` → Metabase, `/` → Web Application -- **Core API** processes user requests and schedules scan jobs via Sidekiq (Redis-backed job queues) -- **Connector API** executes connectors as Kubernetes Jobs to scan data sources -- **Metabase** provides embedded dashboards with JWT-based single sign-on from Core API -- **ArgoCD** continuously monitors the OCI registry for updates and applies changes automatically - -## Namespace Layout - -| Namespace | Contents | -| --- | --- | -| `access-analyzer` | All application workloads (Core API, databases, connectors, Metabase, observability) | -| `argocd` | ArgoCD server, application controller, and repo server | -| `kube-system` | Traefik ingress controller, K3s system components | - -## Data Stores - -| Database | Data Stored | -| --- | --- | -| **PostgreSQL** | Users, sources, scans, service accounts, connector state, configuration | -| **ClickHouse** | Scan results, analytics, OpenTelemetry traces and logs | -| **Redis** | User sessions, Sidekiq job queues, application cache | diff --git a/docs/accessanalyzer/1.0/install/_category_.json b/docs/accessanalyzer/1.0/overview/install/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/install/_category_.json rename to docs/accessanalyzer/1.0/overview/install/_category_.json diff --git a/docs/accessanalyzer/1.0/install/dspmctl.md b/docs/accessanalyzer/1.0/overview/install/dspmctl.md similarity index 100% rename from docs/accessanalyzer/1.0/install/dspmctl.md rename to docs/accessanalyzer/1.0/overview/install/dspmctl.md diff --git a/docs/accessanalyzer/1.0/install/environmentvariables.md b/docs/accessanalyzer/1.0/overview/install/environmentvariables.md similarity index 100% rename from docs/accessanalyzer/1.0/install/environmentvariables.md rename to docs/accessanalyzer/1.0/overview/install/environmentvariables.md diff --git a/docs/accessanalyzer/1.0/install/network.md b/docs/accessanalyzer/1.0/overview/install/network.md similarity index 100% rename from docs/accessanalyzer/1.0/install/network.md rename to docs/accessanalyzer/1.0/overview/install/network.md diff --git a/docs/accessanalyzer/1.0/install/overview.md b/docs/accessanalyzer/1.0/overview/install/overview.md similarity index 100% rename from docs/accessanalyzer/1.0/install/overview.md rename to docs/accessanalyzer/1.0/overview/install/overview.md diff --git a/docs/accessanalyzer/1.0/install/postinstall.md b/docs/accessanalyzer/1.0/overview/install/postinstall.md similarity index 100% rename from docs/accessanalyzer/1.0/install/postinstall.md rename to docs/accessanalyzer/1.0/overview/install/postinstall.md diff --git a/docs/accessanalyzer/1.0/install/preflight.md b/docs/accessanalyzer/1.0/overview/install/preflight.md similarity index 100% rename from docs/accessanalyzer/1.0/install/preflight.md rename to docs/accessanalyzer/1.0/overview/install/preflight.md diff --git a/docs/accessanalyzer/1.0/install/quickinstall.md b/docs/accessanalyzer/1.0/overview/install/quickinstall.md similarity index 100% rename from docs/accessanalyzer/1.0/install/quickinstall.md rename to docs/accessanalyzer/1.0/overview/install/quickinstall.md diff --git a/docs/accessanalyzer/1.0/install/requirements.md b/docs/accessanalyzer/1.0/overview/install/requirements.md similarity index 100% rename from docs/accessanalyzer/1.0/install/requirements.md rename to docs/accessanalyzer/1.0/overview/install/requirements.md diff --git a/docs/accessanalyzer/1.0/install/security.md b/docs/accessanalyzer/1.0/overview/install/security.md similarity index 100% rename from docs/accessanalyzer/1.0/install/security.md rename to docs/accessanalyzer/1.0/overview/install/security.md diff --git a/docs/accessanalyzer/1.0/install/ssl.md b/docs/accessanalyzer/1.0/overview/install/ssl.md similarity index 100% rename from docs/accessanalyzer/1.0/install/ssl.md rename to docs/accessanalyzer/1.0/overview/install/ssl.md diff --git a/docs/accessanalyzer/1.0/install/stepbystep.md b/docs/accessanalyzer/1.0/overview/install/stepbystep.md similarity index 100% rename from docs/accessanalyzer/1.0/install/stepbystep.md rename to docs/accessanalyzer/1.0/overview/install/stepbystep.md diff --git a/docs/accessanalyzer/1.0/install/uninstall.md b/docs/accessanalyzer/1.0/overview/install/uninstall.md similarity index 100% rename from docs/accessanalyzer/1.0/install/uninstall.md rename to docs/accessanalyzer/1.0/overview/install/uninstall.md diff --git a/docs/accessanalyzer/1.0/install/upgrade.md b/docs/accessanalyzer/1.0/overview/install/upgrade.md similarity index 100% rename from docs/accessanalyzer/1.0/install/upgrade.md rename to docs/accessanalyzer/1.0/overview/install/upgrade.md diff --git a/docs/accessanalyzer/1.0/overview/keyconcepts.md b/docs/accessanalyzer/1.0/overview/keyconcepts.md index 409c8cd341..804ce89f01 100644 --- a/docs/accessanalyzer/1.0/overview/keyconcepts.md +++ b/docs/accessanalyzer/1.0/overview/keyconcepts.md @@ -1,7 +1,7 @@ --- title: "Key Concepts" description: "Sources, scans, patterns, identities, and entitlements" -sidebar_position: 30 +sidebar_position: 20 --- # Key Concepts @@ -56,7 +56,7 @@ A **scan** defines what to analyze and how. Access Analyzer supports several sca - **Identity sync scans** — Synchronize users, groups, and roles from IAM sources (Active Directory Inventory, Entra ID Users/Groups/Roles) - **Local Users and Groups scans** — Collect local account data from file servers (auto-created when an access scan is enabled) -Scans are configured during the [Connect Source wizard](/docs/accessanalyzer/1_0/gettingstarted/firstscan/configuringscan) and can be run on demand or scheduled with a cron expression. Each scan run produces a **scan execution** record with status, duration, and results. +Scans can be run on demand or scheduled with a cron expression. Each scan run produces a **scan execution** record with status, duration, and results. ## Identities and Entitlements diff --git a/docs/accessanalyzer/1.0/overview/overview.md b/docs/accessanalyzer/1.0/overview/overview.md index c74a5290d8..6dc74163a7 100644 --- a/docs/accessanalyzer/1.0/overview/overview.md +++ b/docs/accessanalyzer/1.0/overview/overview.md @@ -1,16 +1,16 @@ --- -title: "What is Access Analyzer" +title: "Intro to the Product" description: "Introduction to Netwrix Access Analyzer and its capabilities" sidebar_position: 10 --- -# What is Access Analyzer +# Intro to the Product -Netwrix Access Analyzer is a Data Security Posture Management (DSPM) platform that discovers, classifies, and secures sensitive data across your organization's file systems and cloud services. It provides visibility into who has access to what data, identifies overly permissive access, and detects sensitive data exposure. +Netwrix Access Analyzer is an on-premises Data Security Posture Management (DSPM) platform that discovers, classifies, and secures sensitive data across your organization's file systems. Deployed on your own infrastructure, it provides visibility into who has access to what data, identifies overly permissive access, and detects sensitive data exposure — all without sending data to the cloud. ## Core Capabilities -- **Data Source Discovery** — Connect to file shares (CIFS/SMB), SharePoint Online sites, and other data repositories to inventory content and access permissions +- **Data Source Discovery** — Connect to file shares (CIFS/SMB) and other on-premises data repositories to inventory content and access permissions - **Identity and Access Analysis** — Synchronize with Active Directory, Entra ID, and local groups to map identities, group memberships, and effective permissions - **Sensitive Data Detection** — Scan files for PII, credentials, PHI, and financial records using built-in patterns and custom regex rules, with compliance mappings to GDPR, CCPA, HIPAA, PCI DSS, GLBA, and CMMC - **Dashboards and Reporting** — View findings through embedded Metabase dashboards for data security posture, Active Directory insights, and sensitive data exposure @@ -18,19 +18,19 @@ Netwrix Access Analyzer is a Data Security Posture Management (DSPM) platform th ## How It Works -1. **Configure data sources** — Add file shares, cloud services, and identity providers as data sources, each with an associated service account for authentication +1. **Configure data sources** — Add file shares and identity providers as data sources, each with an associated service account for authentication 2. **Run scans** — Create access scans to enumerate permissions and sensitive data scans to classify content 3. **Review findings** — Analyze results through dashboards, reports, and the scan execution history 4. **Take action** — Identify and remediate overly permissive access, exposed sensitive data, and policy violations ## Deployment Model -Access Analyzer is deployed as a self-contained Kubernetes cluster on a single Linux VM. A one-command installer provisions all required infrastructure — including K3s, ArgoCD, databases, and application services. Updates are managed automatically through ArgoCD GitOps. +Access Analyzer is deployed on-premises as a self-contained Kubernetes cluster on a single Linux VM within your own network. A one-command installer provisions all required infrastructure — including K3s, ArgoCD, databases, and application services. No cloud connectivity is required. Updates are managed through ArgoCD GitOps. -For installation instructions, see [Installation](/docs/accessanalyzer/1_0/install/overview). +For installation instructions, see [Installation](/docs/accessanalyzer/1_0/overview/install/overview). ## What's Next -- [Architecture Overview](/docs/accessanalyzer/1_0/overview/architecture) — Understand the platform components and how they interact - [Key Concepts](/docs/accessanalyzer/1_0/overview/keyconcepts) — Learn the terminology used throughout Access Analyzer -- [Getting Started](/docs/accessanalyzer/1_0/gettingstarted/overview) — Begin configuring your first data source and scan +- [Requirements](/docs/accessanalyzer/1_0/overview/requirements/overview) — Review system and connector requirements +- [Installation](/docs/accessanalyzer/1_0/overview/install/overview) — Install Access Analyzer on your infrastructure diff --git a/docs/accessanalyzer/1.0/requirements/_category_.json b/docs/accessanalyzer/1.0/overview/requirements/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/requirements/_category_.json rename to docs/accessanalyzer/1.0/overview/requirements/_category_.json diff --git a/docs/accessanalyzer/1.0/requirements/connectors/_category_.json b/docs/accessanalyzer/1.0/overview/requirements/connectors/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/requirements/connectors/_category_.json rename to docs/accessanalyzer/1.0/overview/requirements/connectors/_category_.json diff --git a/docs/accessanalyzer/1.0/requirements/connectors/activedirectory.md b/docs/accessanalyzer/1.0/overview/requirements/connectors/activedirectory.md similarity index 100% rename from docs/accessanalyzer/1.0/requirements/connectors/activedirectory.md rename to docs/accessanalyzer/1.0/overview/requirements/connectors/activedirectory.md diff --git a/docs/accessanalyzer/1.0/requirements/connectors/cifs.md b/docs/accessanalyzer/1.0/overview/requirements/connectors/cifs.md similarity index 100% rename from docs/accessanalyzer/1.0/requirements/connectors/cifs.md rename to docs/accessanalyzer/1.0/overview/requirements/connectors/cifs.md diff --git a/docs/accessanalyzer/1.0/requirements/connectors/entraid.md b/docs/accessanalyzer/1.0/overview/requirements/connectors/entraid.md similarity index 100% rename from docs/accessanalyzer/1.0/requirements/connectors/entraid.md rename to docs/accessanalyzer/1.0/overview/requirements/connectors/entraid.md diff --git a/docs/accessanalyzer/1.0/requirements/connectors/localgroups.md b/docs/accessanalyzer/1.0/overview/requirements/connectors/localgroups.md similarity index 100% rename from docs/accessanalyzer/1.0/requirements/connectors/localgroups.md rename to docs/accessanalyzer/1.0/overview/requirements/connectors/localgroups.md diff --git a/docs/accessanalyzer/1.0/requirements/connectors/sharepointonline.md b/docs/accessanalyzer/1.0/overview/requirements/connectors/sharepointonline.md similarity index 100% rename from docs/accessanalyzer/1.0/requirements/connectors/sharepointonline.md rename to docs/accessanalyzer/1.0/overview/requirements/connectors/sharepointonline.md diff --git a/docs/accessanalyzer/1.0/requirements/database/_category_.json b/docs/accessanalyzer/1.0/overview/requirements/database/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/requirements/database/_category_.json rename to docs/accessanalyzer/1.0/overview/requirements/database/_category_.json diff --git a/docs/accessanalyzer/1.0/requirements/database/clickhouse.md b/docs/accessanalyzer/1.0/overview/requirements/database/clickhouse.md similarity index 100% rename from docs/accessanalyzer/1.0/requirements/database/clickhouse.md rename to docs/accessanalyzer/1.0/overview/requirements/database/clickhouse.md diff --git a/docs/accessanalyzer/1.0/requirements/database/postgresql.md b/docs/accessanalyzer/1.0/overview/requirements/database/postgresql.md similarity index 100% rename from docs/accessanalyzer/1.0/requirements/database/postgresql.md rename to docs/accessanalyzer/1.0/overview/requirements/database/postgresql.md diff --git a/docs/accessanalyzer/1.0/requirements/database/redis.md b/docs/accessanalyzer/1.0/overview/requirements/database/redis.md similarity index 100% rename from docs/accessanalyzer/1.0/requirements/database/redis.md rename to docs/accessanalyzer/1.0/overview/requirements/database/redis.md diff --git a/docs/accessanalyzer/1.0/requirements/overview.md b/docs/accessanalyzer/1.0/overview/requirements/overview.md similarity index 100% rename from docs/accessanalyzer/1.0/requirements/overview.md rename to docs/accessanalyzer/1.0/overview/requirements/overview.md diff --git a/docs/accessanalyzer/1.0/requirements/system/_category_.json b/docs/accessanalyzer/1.0/overview/requirements/system/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/requirements/system/_category_.json rename to docs/accessanalyzer/1.0/overview/requirements/system/_category_.json diff --git a/docs/accessanalyzer/1.0/requirements/system/hardware.md b/docs/accessanalyzer/1.0/overview/requirements/system/hardware.md similarity index 100% rename from docs/accessanalyzer/1.0/requirements/system/hardware.md rename to docs/accessanalyzer/1.0/overview/requirements/system/hardware.md diff --git a/docs/accessanalyzer/1.0/requirements/system/kubernetes.md b/docs/accessanalyzer/1.0/overview/requirements/system/kubernetes.md similarity index 100% rename from docs/accessanalyzer/1.0/requirements/system/kubernetes.md rename to docs/accessanalyzer/1.0/overview/requirements/system/kubernetes.md diff --git a/docs/accessanalyzer/1.0/requirements/system/network.md b/docs/accessanalyzer/1.0/overview/requirements/system/network.md similarity index 100% rename from docs/accessanalyzer/1.0/requirements/system/network.md rename to docs/accessanalyzer/1.0/overview/requirements/system/network.md diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/_category_.json b/docs/accessanalyzer/1.0/sensitivedatadiscovery/_category_.json deleted file mode 100644 index 6bf6249468..0000000000 --- a/docs/accessanalyzer/1.0/sensitivedatadiscovery/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Sensitive Data Discovery", - "position": 70, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/overview.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/overview.md deleted file mode 100644 index f534a637e7..0000000000 --- a/docs/accessanalyzer/1.0/sensitivedatadiscovery/overview.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: "Sensitive Data Discovery" -description: "Discover and classify sensitive data across your environment" -sidebar_position: 1 ---- - -# Sensitive Data Discovery - -Sensitive Data Discovery (SDD) in Netwrix Access Analyzer identifies and classifies sensitive information across your connected data sources. The platform uses two complementary detection methods: the Netwrix Data Classification SDK and custom regex pattern matching. - -## Workflow - -Follow these steps to discover sensitive data in your environment: - -1. **Configure detection patterns** — Select from [built-in patterns](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/builtinpatterns) or [create custom regex patterns](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/custompatterns) to define what constitutes sensitive data. -2. **Organize patterns into groups** — Use [pattern groups](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/patterngroups) to logically categorize your detection patterns. -3. **Map to compliance frameworks** — Configure [taxonomy groups](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/taxonomygroups) and [classification rules](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/classificationrules) to align findings with regulatory requirements. -4. **Run a scan** — [Execute a sensitive data scan](/docs/accessanalyzer/1_0/sensitivedatadiscovery/runningscan) against your target data sources. -5. **Review results** — Analyze [match counts](/docs/accessanalyzer/1_0/sensitivedatadiscovery/reviewingresults/matchcounts) and [classification breakdowns](/docs/accessanalyzer/1_0/sensitivedatadiscovery/reviewingresults/classificationbreakdown) to understand your data risk posture. - -## Supported Data Types - -| Category | Examples | -| --- | --- | -| PII | Social Security numbers, names, addresses, email addresses | -| Credentials | Passwords, API keys, authentication tokens | -| PHI | Medical records, health data, insurance identifiers | -| Financial Records | Credit card numbers, bank account details | - -:::note -Sensitive data scans are configured during the scan creation wizard. Ensure your detection patterns and taxonomy mappings are in place before running your first scan. -::: diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/_category_.json b/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/_category_.json deleted file mode 100644 index 868656ec39..0000000000 --- a/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Configuring Patterns", - "position": 20, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "builtinpatterns" - } -} diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/builtinpatterns.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/builtinpatterns.md deleted file mode 100644 index 0653231675..0000000000 --- a/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/builtinpatterns.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: "Built-in Patterns" -description: "Pre-configured patterns for PII, PCI, SSN, and more" -sidebar_position: 10 ---- - -# Built-in Patterns - -Netwrix Access Analyzer ships with a library of pre-configured detection patterns that identify common categories of sensitive data. These built-in patterns use the Netwrix Data Classification SDK and are ready to use without additional configuration. - -## Pattern Categories - -| Category | Description | Examples | -| --- | --- | --- | -| PII | Personally identifiable information | Social Security numbers, full names, mailing addresses, email addresses, phone numbers | -| Credentials | Authentication and access secrets | Passwords, API keys, tokens, private keys, connection strings | -| PHI | Protected health information | Medical record numbers, health plan IDs, diagnosis codes, lab results | -| Financial Records | Payment and banking data | Credit card numbers (PAN), bank account and routing numbers, tax IDs | - -## How Built-in Patterns Work - -Built-in patterns leverage two detection methods: - -- **Netwrix Data Classification SDK** — A C#/.NET-based engine that applies advanced heuristics and contextual analysis beyond simple pattern matching. -- **Regex pattern matching** — Standard regular expressions tuned for high-accuracy detection of structured data formats such as SSNs, credit card numbers, and IBANs. - -:::note -Built-in patterns cannot be edited directly. To modify detection behavior, create a [custom pattern](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/custompatterns) and organize it into a [pattern group](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/patterngroups). -::: - -## Next Steps - -- [Create custom regex patterns](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/custompatterns) for organization-specific data formats -- [Organize patterns into groups](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/patterngroups) for streamlined scan configuration diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/custompatterns.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/custompatterns.md deleted file mode 100644 index 8645e34568..0000000000 --- a/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/custompatterns.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: "Creating Custom Regex Patterns" -description: "Define custom regex patterns for sensitive data detection" -sidebar_position: 20 ---- - -# Creating Custom Regex Patterns - -Custom regex patterns allow you to extend sensitive data detection beyond the built-in library. Define patterns that match organization-specific data formats such as internal account numbers, proprietary identifiers, or region-specific document formats. - -## Creating a Custom Pattern - -To create a custom regex pattern: - -1. Navigate to the **Sensitive Data Discovery** section in Access Analyzer. -2. Select **Patterns** and click **Add Pattern**. -3. Provide a **Name** and optional **Description** for the pattern. -4. Enter the **Regex Expression** that defines the match criteria. -5. Select the appropriate **Category** (PII, Credentials, PHI, or Financial Records). -6. Click **Save** to register the pattern. - -:::note -Custom patterns can also be added programmatically via the Access Analyzer API. Refer to the API documentation for endpoint details and payload format. -::: - -## Regex Best Practices - -- **Be specific** — Overly broad patterns increase false positives. Use anchors, character classes, and quantifiers to narrow matches. -- **Test before deploying** — Validate your regex against sample data to confirm it captures the intended formats without excessive noise. -- **Use named groups** — Where supported, named capture groups improve readability and facilitate downstream processing. - -## Example - -A pattern to detect a custom internal employee ID formatted as `EMP-` followed by six digits: - -``` -EMP-\d{6} -``` - -:::warning -Poorly constructed regex patterns may degrade scan performance. Avoid unbounded quantifiers and excessive backtracking in pattern definitions. -::: - -## Next Steps - -- [Organize patterns into groups](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/patterngroups) for easier management -- [Map patterns to compliance frameworks](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/taxonomygroups) using taxonomy groups diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/patterngroups.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/patterngroups.md deleted file mode 100644 index 9643c03154..0000000000 --- a/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/patterngroups.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: "Pattern Groups" -description: "Organizing patterns into logical groups" -sidebar_position: 30 ---- - -# Pattern Groups - -Pattern groups organize individual detection patterns into logical collections. Grouping patterns by category or purpose simplifies scan configuration and makes it easier to apply consistent detection policies across multiple scans. - -## How Pattern Groups Work - -A pattern group is a named container that holds one or more detection patterns (built-in or custom). When you configure a sensitive data scan, you select pattern groups rather than individual patterns, which reduces configuration complexity. - -Common grouping strategies include: - -- **By data type** — Group all PII patterns together, all credential patterns together, and so on. -- **By compliance framework** — Group patterns that satisfy a specific regulation such as HIPAA or PCI DSS. -- **By business unit** — Group patterns relevant to a particular department or data domain. - -## Managing Pattern Groups - -To create or edit a pattern group: - -1. Navigate to **Sensitive Data Discovery** > **Patterns**. -2. Select the **Pattern Groups** tab. -3. Click **Add Group** to create a new group, or select an existing group to edit it. -4. Provide a **Name** and optional **Description**. -5. Add or remove patterns from the group using the pattern selector. -6. Click **Save**. - -:::note -A single pattern can belong to multiple groups. Changes to a pattern are reflected in all groups that reference it. -::: - -## Next Steps - -- [Configure taxonomy groups](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/taxonomygroups) to map pattern groups to compliance frameworks -- [Run a sensitive data scan](/docs/accessanalyzer/1_0/sensitivedatadiscovery/runningscan) using your configured pattern groups diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/_category_.json b/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/_category_.json deleted file mode 100644 index 8d68d0c5ea..0000000000 --- a/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Reviewing Results", - "position": 50, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "matchcounts" - } -} diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/classificationbreakdown.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/classificationbreakdown.md deleted file mode 100644 index 74a5711b20..0000000000 --- a/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/classificationbreakdown.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: "Classification Breakdown" -description: "Analyzing results by classification category" -sidebar_position: 20 ---- - -# Classification Breakdown - -The classification breakdown view organizes sensitive data scan results by taxonomy group and compliance framework. This view helps you assess regulatory exposure and prioritize remediation efforts based on the frameworks most relevant to your organization. - -## Viewing the Breakdown - -To access the classification breakdown: - -1. Navigate to the **Scans** section and select a completed scan. -2. Open the **Results** tab. -3. Select the **Classification Breakdown** view. - -The breakdown displays a summary of matches grouped by each applicable compliance framework. - -## Framework Summary - -| Column | Description | -| --- | --- | -| **Framework** | The compliance standard (GDPR, CCPA, HIPAA, PCI DSS, GLBA, CMMC) | -| **Total Matches** | Aggregate count of sensitive data matches mapped to this framework | -| **Files Affected** | Number of distinct files containing matches for this framework | -| **Top Patterns** | The most frequently triggered detection patterns within the framework | - -## Interpreting Results - -- A file may appear under multiple frameworks if its contents match classification rules mapped to different taxonomy groups. -- The **Top Patterns** column highlights which data types contribute the most matches, helping you identify the most common exposure areas. -- Use the breakdown to generate framework-specific remediation plans by focusing on the frameworks with the highest match counts. - -:::note -Classification breakdown results depend on the [taxonomy groups](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/taxonomygroups) and [classification rules](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/classificationrules) configured at the time of the scan. Update your taxonomy mappings and re-scan to reflect new compliance requirements. -::: - -## Next Steps - -- [Export findings](/docs/accessanalyzer/1_0/dashboards/metabase/exportingdata) for compliance reporting -- [View dashboards](/docs/accessanalyzer/1_0/dashboards/overview) for a high-level risk summary diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/matchcounts.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/matchcounts.md deleted file mode 100644 index 2dd3d19f26..0000000000 --- a/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/matchcounts.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: "Match Counts and Locations" -description: "Viewing match counts per file and location details" -sidebar_position: 10 ---- - -# Match Counts and Locations - -After a sensitive data scan completes, the results view displays match counts that summarize how many sensitive data instances were detected, organized by file, pattern, and compliance framework. - -## Understanding Match Counts - -Match counts are reported at three levels: - -| Level | Description | -| --- | --- | -| **Per File** | Total number of sensitive data matches found in each scanned file | -| **Per Pattern** | Number of matches attributed to each detection pattern (for example, SSN, credit card number) | -| **Per Framework** | Aggregate match count grouped by compliance framework (GDPR, HIPAA, PCI DSS, and others) | - -## Viewing Match Details - -To review match counts for a completed scan: - -1. Navigate to the **Scans** section and select the completed scan. -2. Open the **Results** tab to view the summary. -3. Use the **Files** view to see match counts per file, sorted by the number of matches in descending order. -4. Click on a specific file to view the individual pattern matches detected within it. -5. Use the **Patterns** view to see total matches per detection pattern across all scanned files. - -:::note -Match counts reflect the number of pattern matches, not the number of unique sensitive data values. A single file containing the same SSN in multiple locations is counted as multiple matches. -::: - -## Filtering Results - -Use the filter controls to narrow results by: - -- **Data type** — PII, Credentials, PHI, or Financial Records -- **Pattern group** — Filter by a specific pattern group applied during the scan -- **Severity** — Focus on high-priority findings - -## Next Steps - -- [View classification breakdowns](/docs/accessanalyzer/1_0/sensitivedatadiscovery/reviewingresults/classificationbreakdown) to analyze results by compliance framework -- [Access dashboards](/docs/accessanalyzer/1_0/dashboards/overview) for a visual summary of findings diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/runningscan.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/runningscan.md deleted file mode 100644 index 78306fe3bc..0000000000 --- a/docs/accessanalyzer/1.0/sensitivedatadiscovery/runningscan.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: "Running a Sensitive Data Scan" -description: "Executing a sensitive data scan and monitoring progress" -sidebar_position: 40 ---- - -# Running a Sensitive Data Scan - -Sensitive data scans analyze files across your connected data sources to detect content matching your configured detection patterns. Scans are configured and launched through the scan creation wizard. - -## Prerequisites - -Before running a sensitive data scan, ensure the following are in place: - -- At least one data source is connected and accessible -- Detection [patterns](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/builtinpatterns) or [pattern groups](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/patterngroups) are configured -- [Taxonomy groups](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/taxonomygroups) and [classification rules](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/classificationrules) are defined for compliance mapping - -## Launching a Scan - -1. Navigate to the **Scans** section in Access Analyzer. -2. Click **Create Scan** to open the scan creation wizard. -3. Select the target **Data Source(s)** to scan. -4. Under **Scan Options**, enable **Sensitive Data Discovery**. -5. Choose the **Pattern Groups** to apply during the scan. -6. Review the scan configuration summary and click **Start Scan**. - -## Monitoring Progress - -Once a scan is running, you can monitor its status from the **Scans** page. The scan detail view displays: - -- **Progress** — Percentage of files processed -- **Files Scanned** — Count of files analyzed so far -- **Matches Found** — Running total of sensitive data matches - -:::warning -Sensitive data scans are resource-intensive. The `sensitive-data-scan` and `data-classification` serverless functions handle detection workloads. Schedule large scans during off-peak hours to minimize impact on system performance. -::: - -## Next Steps - -- [Review match counts](/docs/accessanalyzer/1_0/sensitivedatadiscovery/reviewingresults/matchcounts) after the scan completes -- [Analyze classification breakdowns](/docs/accessanalyzer/1_0/sensitivedatadiscovery/reviewingresults/classificationbreakdown) by compliance framework diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/_category_.json b/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/_category_.json deleted file mode 100644 index ce0fe0e2ed..0000000000 --- a/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Taxonomy and Classification", - "position": 30, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "taxonomygroups" - } -} diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/autovscustom.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/autovscustom.md deleted file mode 100644 index 0f6c9de35d..0000000000 --- a/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/autovscustom.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: "Auto vs Custom Classification" -description: "Automatic and custom classification methods" -sidebar_position: 30 ---- - -# Auto vs Custom Classification - -Netwrix Access Analyzer supports two classification approaches for sensitive data: automatic (built-in) classification and custom classification. You can use either method independently or combine them for comprehensive coverage. - -## Automatic Classification - -Automatic classification uses the built-in patterns and taxonomy groups that ship with Access Analyzer. This approach requires no upfront configuration and covers common sensitive data categories out of the box. - -**Advantages:** - -- Ready to use immediately after installation -- Covers standard compliance frameworks (GDPR, CCPA, HIPAA, PCI DSS, GLBA, CMMC) -- Maintained and updated by Netwrix through the Data Classification SDK - -**Best for:** Organizations that need quick time-to-value and standard regulatory coverage. - -## Custom Classification - -Custom classification uses organization-defined regex patterns, pattern groups, and taxonomy mappings. This approach provides full control over what data is detected and how it is categorized. - -**Advantages:** - -- Detects proprietary or non-standard data formats -- Maps findings to internal policies beyond standard frameworks -- Supports region-specific or industry-specific identifiers - -**Best for:** Organizations with unique data formats or compliance requirements not covered by built-in rules. - -## Combining Both Approaches - -For most deployments, a hybrid approach provides the best coverage. Use automatic classification as a baseline, then layer custom patterns for organization-specific needs. - -:::note -Custom rules take precedence over automatic rules when both match the same data and the custom rule has a higher priority. See [Classification Rules](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/classificationrules) for details on priority settings. -::: diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/classificationrules.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/classificationrules.md deleted file mode 100644 index 028e7e4ed0..0000000000 --- a/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/classificationrules.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: "Classification Rules" -description: "Defining rules that combine patterns and taxonomy" -sidebar_position: 20 ---- - -# Classification Rules - -Classification rules connect detection patterns to taxonomy groups, determining how identified sensitive data is categorized and which compliance frameworks apply to each finding. A rule specifies the conditions under which a pattern match is classified under a particular taxonomy. - -## Rule Components - -Each classification rule consists of: - -| Component | Description | -| --- | --- | -| **Name** | A descriptive label for the rule | -| **Pattern or Pattern Group** | The detection patterns that trigger the rule | -| **Taxonomy Group** | The compliance framework or category the match maps to | -| **Priority** | Determines precedence when multiple rules match the same data | - -## Creating a Classification Rule - -1. Navigate to **Sensitive Data Discovery** > **Taxonomy**. -2. Select the **Classification Rules** tab. -3. Click **Add Rule**. -4. Enter a **Name** for the rule. -5. Select the **Pattern** or **Pattern Group** that triggers this classification. -6. Choose the **Taxonomy Group** the rule maps to (for example, HIPAA, PCI DSS, or a custom group). -7. Set the **Priority** level to control rule precedence. -8. Click **Save**. - -:::note -When a single file matches multiple classification rules, all applicable taxonomy groups are reported. Priority determines which classification is displayed first in summary views. -::: - -## Next Steps - -- [Review built-in versus custom classification](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/autovscustom) to decide which approach fits your needs -- [Run a scan](/docs/accessanalyzer/1_0/sensitivedatadiscovery/runningscan) to apply your classification rules against live data diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/taxonomygroups.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/taxonomygroups.md deleted file mode 100644 index 54e9e01635..0000000000 --- a/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/taxonomygroups.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: "Taxonomy Groups" -description: "Creating and managing data classification categories" -sidebar_position: 10 ---- - -# Taxonomy Groups - -Taxonomy groups map classification rules to compliance frameworks, enabling you to align sensitive data findings with regulatory and organizational requirements. Each taxonomy group represents a compliance standard or internal policy against which scan results are evaluated. - -## Supported Compliance Frameworks - -Access Analyzer includes built-in taxonomy groups for the following frameworks: - -| Framework | Description | -| --- | --- | -| GDPR | General Data Protection Regulation — EU personal data protection | -| CCPA | California Consumer Privacy Act — California resident data rights | -| HIPAA | Health Insurance Portability and Accountability Act — protected health information | -| PCI DSS | Payment Card Industry Data Security Standard — cardholder data protection | -| GLBA | Gramm-Leach-Bliley Act — financial institution consumer data | -| CMMC | Cybersecurity Maturity Model Certification — defense contractor requirements | - -## Managing Taxonomy Groups - -To create or modify a taxonomy group: - -1. Navigate to **Sensitive Data Discovery** > **Taxonomy**. -2. Select the **Taxonomy Groups** tab. -3. Click **Add Group** to create a new group, or select an existing group to edit. -4. Provide a **Name** and select the target **Compliance Framework**. -5. Associate [classification rules](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/classificationrules) that define which data types fall under this group. -6. Click **Save**. - -:::note -Built-in taxonomy groups are pre-mapped to their respective frameworks. You can create additional groups for internal policies or regional regulations not covered by the defaults. -::: - -## Next Steps - -- [Define classification rules](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/classificationrules) to control how data is categorized within each taxonomy group -- [Compare built-in and custom classification](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/autovscustom) approaches diff --git a/docs/accessanalyzer/1.0/troubleshooting/_category_.json b/docs/accessanalyzer/1.0/troubleshooting/_category_.json deleted file mode 100644 index 53df54fda4..0000000000 --- a/docs/accessanalyzer/1.0/troubleshooting/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Monitoring and Troubleshooting", - "position": 100, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/troubleshooting/commonissues/_category_.json b/docs/accessanalyzer/1.0/troubleshooting/commonissues/_category_.json deleted file mode 100644 index feba67eef4..0000000000 --- a/docs/accessanalyzer/1.0/troubleshooting/commonissues/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Common Issues", - "position": 40, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "connectionfailures" - } -} diff --git a/docs/accessanalyzer/1.0/troubleshooting/commonissues/connectionfailures.md b/docs/accessanalyzer/1.0/troubleshooting/commonissues/connectionfailures.md deleted file mode 100644 index f13e0f0872..0000000000 --- a/docs/accessanalyzer/1.0/troubleshooting/commonissues/connectionfailures.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: "Connection Failures" -description: "Diagnosing and resolving connector connection issues" -sidebar_position: 10 ---- - -# Connection Failures - -Access Analyzer connects to external data sources using protocols such as SMB, LDAP, and Microsoft Graph API. Connection failures prevent scans from running and must be resolved before data collection can proceed. - -## Diagnostic Steps - -1. **Check the connector-api pod status:** - -```bash -kubectl get pods -n access-analyzer -l app=connector-api -kubectl logs -n access-analyzer deploy/connector-api --tail=100 -``` - -2. **Verify network connectivity** from the connector pod to the target: - -```bash -kubectl exec -n access-analyzer deploy/connector-api -- curl -v https://: -``` - -3. **Review the source configuration** in the Access Analyzer web UI. Confirm that the hostname, port, and credentials are correct. - -## SMB Connection Failures - -- Verify that TCP port **445** is open between the Access Analyzer cluster and the target file server. -- Confirm that the service account has the required share and NTFS permissions. -- Check for DNS resolution issues by running `nslookup ` from within the connector pod. - -## LDAP Connection Failures - -- Verify that TCP port **389** (LDAP) or **636** (LDAPS) is reachable. -- Confirm that the bind DN and password are correct. -- For LDAPS, ensure the target server's TLS certificate is trusted. Self-signed certificates may require adding a CA bundle. - -## Microsoft Graph API Failures - -- Confirm that the Azure AD application registration has the required API permissions. -- Verify that the client ID, client secret, and tenant ID are correct and that the secret has not expired. -- Check outbound HTTPS connectivity to `https://graph.microsoft.com` and `https://login.microsoftonline.com`. - -```bash -kubectl exec -n access-analyzer deploy/connector-api -- curl -s -o /dev/null -w "%{http_code}" https://graph.microsoft.com/v1.0/ -``` - -## General Troubleshooting - -| Symptom | Likely Cause | Action | -| --- | --- | --- | -| Connection timeout | Firewall or network policy blocking traffic | Verify firewall rules and Kubernetes network policies | -| Authentication error | Invalid or expired credentials | Update credentials in the source configuration | -| TLS handshake failure | Certificate mismatch or expired certificate | Verify TLS certificates on the target service | -| DNS resolution failure | Incorrect hostname or missing DNS entry | Test DNS from within the connector pod | - -:::note -Connection tests run from the `connector-api` pod. Network access from your local machine does not guarantee access from within the cluster. -::: diff --git a/docs/accessanalyzer/1.0/troubleshooting/commonissues/databaseconnectivity.md b/docs/accessanalyzer/1.0/troubleshooting/commonissues/databaseconnectivity.md deleted file mode 100644 index fb2aebe74c..0000000000 --- a/docs/accessanalyzer/1.0/troubleshooting/commonissues/databaseconnectivity.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: "Database Connectivity" -description: "Resolving PostgreSQL, ClickHouse, and Redis connectivity issues" -sidebar_position: 30 ---- - -# Database Connectivity - -Access Analyzer relies on three backing data stores: PostgreSQL for relational data, ClickHouse for analytics and trace storage, and Redis for sessions, caching, and job queues. Connectivity failures to any of these services impact application functionality. - -## Checking Pod Status - -**Verify that all database pods are running:** - -```bash -kubectl get pods -n access-analyzer -l app=postgresql -kubectl get pods -n access-analyzer -l app=clickhouse -kubectl get pods -n access-analyzer -l app=redis -``` - -A pod not in `Running` status requires immediate attention. Use `kubectl describe pod -n access-analyzer` to inspect events and error details. - -## PostgreSQL - -PostgreSQL stores core application data including user accounts, source configurations, and scan results. - -**Test connectivity from the core-api pod:** - -```bash -kubectl exec -n access-analyzer deploy/core-api -- pg_isready -h postgresql -p 5432 -``` - -**Check active connections:** - -```bash -kubectl exec -n access-analyzer deploy/postgresql -- psql -U postgres -c "SELECT count(*) FROM pg_stat_activity;" -``` - -Common issues: -- **Too many connections** -- The connection pool is exhausted. Restart the application pods or increase the pool size. -- **Pod in CrashLoopBackOff** -- Check PostgreSQL logs for disk space or corruption errors. - -## ClickHouse - -ClickHouse stores analytics data and OpenTelemetry traces in the `access_analyzer_logs` database. - -**Test connectivity:** - -```bash -kubectl exec -n access-analyzer deploy/clickhouse -- clickhouse-client --query "SELECT 1" -``` - -**Check database availability:** - -```bash -kubectl exec -n access-analyzer deploy/clickhouse -- clickhouse-client --query "SHOW DATABASES" -``` - -Common issues: -- **Disk pressure** -- ClickHouse can consume significant storage for trace and analytics data. Monitor disk usage with `kubectl exec -n access-analyzer deploy/clickhouse -- df -h`. -- **Query timeout** -- Large analytical queries can time out. Check ClickHouse server logs for slow query warnings. - -## Redis - -Redis provides session storage, caching, and serves as the job queue backend for Sidekiq. - -**Test connectivity:** - -```bash -kubectl exec -n access-analyzer deploy/redis -- redis-cli ping -``` - -A successful response returns `PONG`. - -**Check memory usage:** - -```bash -kubectl exec -n access-analyzer deploy/redis -- redis-cli info memory | grep used_memory_human -``` - -Common issues: -- **MaxMemory reached** -- Redis evicts keys or rejects writes when memory is full. Increase the memory limit or review eviction policies. -- **Connection refused** -- The Redis pod may have restarted. Check pod status and events. - -## Deep Health Check - -Use the application health endpoint to validate connectivity to all backing services at once: - -```bash -kubectl exec -n access-analyzer deploy/core-api -- curl -s http://localhost:3000/api/v1/monitoring/__health -``` - -This endpoint reports the status of each backing service and identifies which connection is failing. See [Service Health Endpoints](/docs/accessanalyzer/1.0/troubleshooting/healthchecks/endpoints) for more details. - -:::warning -Database connectivity failures cascade across the application. If multiple services report errors simultaneously, start by verifying database pod health before troubleshooting individual application pods. -::: diff --git a/docs/accessanalyzer/1.0/troubleshooting/commonissues/scanerrors.md b/docs/accessanalyzer/1.0/troubleshooting/commonissues/scanerrors.md deleted file mode 100644 index 4bd3cf333c..0000000000 --- a/docs/accessanalyzer/1.0/troubleshooting/commonissues/scanerrors.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: "Scan Errors" -description: "Common scan execution errors and solutions" -sidebar_position: 20 ---- - -# Scan Errors - -Scan errors occur when Access Analyzer encounters problems during data collection from configured sources. This page covers common scan errors, their causes, and resolution steps. - -## Checking Scan Status - -Review scan status in the Access Analyzer web UI or check the logs from the relevant pods: - -```bash -kubectl logs -n access-analyzer deploy/core-api --tail=200 | grep -i scan -kubectl logs -n access-analyzer deploy/connector-api --tail=200 | grep -i scan -``` - -## Common Scan Errors - -### Scan Timeout - -Scans that exceed the configured timeout are terminated automatically. - -- **Cause**: Large data sources, slow network connectivity, or insufficient worker resources. -- **Resolution**: Increase the scan timeout if appropriate, reduce the scan scope, or allocate additional resources to worker pods. - -### Pod Failures During Scan - -If the pod executing a scan is killed or restarted mid-scan, the scan fails without completing. - -```bash -kubectl get pods -n access-analyzer --field-selector=status.phase=Failed -kubectl describe pod -n access-analyzer -``` - -- **Cause**: OOMKilled (out of memory), node eviction, or liveness probe timeout. -- **Resolution**: Check pod events for `OOMKilled` status. Increase memory limits for the affected pod if needed. Review node resource pressure with `kubectl top nodes`. - -### Permission Denied Errors - -The scan account lacks the required permissions on the target data source. - -- **Cause**: Insufficient privileges for the configured service account. -- **Resolution**: Verify that the service account has the permissions documented for the source type. See [Connection Failures](/docs/accessanalyzer/1.0/troubleshooting/commonissues/connectionfailures) for protocol-specific requirements. - -### Partial Scan Results - -A scan completes but returns fewer results than expected. - -- **Cause**: Access denied on a subset of resources, or rate limiting by the target API. -- **Resolution**: Review the scan logs for warnings about skipped resources. For API-based sources, check for throttling responses (HTTP 429). - -## Reviewing Scan Job History - -Failed scan jobs appear in the Sidekiq **Retries** or **Dead** tab. See [Failed Job Troubleshooting](/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/failedjobs) for instructions on inspecting and retrying failed jobs. - -:::warning -If scans fail consistently across multiple sources, check cluster-wide resource availability and backing service health before investigating individual source configurations. -::: diff --git a/docs/accessanalyzer/1.0/troubleshooting/healthchecks/_category_.json b/docs/accessanalyzer/1.0/troubleshooting/healthchecks/_category_.json deleted file mode 100644 index affcb1f52d..0000000000 --- a/docs/accessanalyzer/1.0/troubleshooting/healthchecks/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Health Checks", - "position": 10, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "probes" - } -} diff --git a/docs/accessanalyzer/1.0/troubleshooting/healthchecks/endpoints.md b/docs/accessanalyzer/1.0/troubleshooting/healthchecks/endpoints.md deleted file mode 100644 index 772ef5edf7..0000000000 --- a/docs/accessanalyzer/1.0/troubleshooting/healthchecks/endpoints.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: "Service Health Endpoints" -description: "Service-specific health check URLs" -sidebar_position: 20 ---- - -# Service Health Endpoints - -Access Analyzer exposes several HTTP health check endpoints that report on service availability. Use these endpoints to verify that application services are running and responsive. - -## Available Endpoints - -| Endpoint | Purpose | Expected Response | -| --- | --- | --- | -| `/health/live` | Liveness check. Confirms the process is running. | `200 OK` | -| `/health/ready` | Readiness check. Confirms the service can handle requests. | `200 OK` | -| `/api/v1/monitoring/__health` | Deep health check. Validates connectivity to backing services (database, cache). | `200 OK` with JSON status | - -## Querying Health Endpoints - -**From within the cluster, use `kubectl exec` to curl a health endpoint:** - -```bash -kubectl exec -n access-analyzer deploy/core-api -- curl -s http://localhost:3000/health/live -``` - -**Check the readiness endpoint:** - -```bash -kubectl exec -n access-analyzer deploy/core-api -- curl -s http://localhost:3000/health/ready -``` - -**Run the deep health check to verify backing service connectivity:** - -```bash -kubectl exec -n access-analyzer deploy/core-api -- curl -s http://localhost:3000/api/v1/monitoring/__health -``` - -The deep health check at `/api/v1/monitoring/__health` validates that the application can reach PostgreSQL, ClickHouse, and Redis. A failure response from this endpoint identifies which backing service is unreachable. - -## Interpreting Results - -- A `200 OK` response indicates the service is healthy. -- A non-200 response or connection timeout indicates a problem. Check the pod logs for additional context. -- If `/health/live` passes but `/health/ready` fails, the service is running but cannot process requests, typically due to a dependency being unavailable. - -:::note -The `/api/v1/monitoring/__health` endpoint performs active checks against all backing services. Use it for thorough health verification, but avoid calling it at high frequency as it places load on downstream systems. -::: diff --git a/docs/accessanalyzer/1.0/troubleshooting/healthchecks/probes.md b/docs/accessanalyzer/1.0/troubleshooting/healthchecks/probes.md deleted file mode 100644 index 8f2b0697b8..0000000000 --- a/docs/accessanalyzer/1.0/troubleshooting/healthchecks/probes.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: "Liveness and Readiness Probes" -description: "Kubernetes health probe endpoints" -sidebar_position: 10 ---- - -# Liveness and Readiness Probes - -Kubernetes uses liveness and readiness probes to monitor the health of pods in the Access Analyzer deployment. Understanding these probes helps you diagnose pod restarts and service availability issues. - -## How Probes Work - -- **Liveness probes** determine whether a container is running. If a liveness probe fails, Kubernetes restarts the container. -- **Readiness probes** determine whether a container is ready to accept traffic. If a readiness probe fails, Kubernetes removes the pod from service endpoints until it passes again. - -## Checking Probe Status - -**View the current state of all pods in the Access Analyzer namespace:** - -```bash -kubectl get pods -n access-analyzer -``` - -A pod in `CrashLoopBackOff` status typically indicates repeated liveness probe failures. A pod showing `0/1 Ready` may be failing its readiness probe. - -**Inspect probe configuration and recent events for a specific pod:** - -```bash -kubectl describe pod -n access-analyzer -``` - -Look for the `Liveness` and `Readiness` fields in the output to see the probe endpoint, interval, timeout, and failure threshold. The **Events** section at the bottom shows recent probe failures and container restarts. - -**View logs from a pod that is restarting:** - -```bash -kubectl logs -n access-analyzer --previous -``` - -The `--previous` flag retrieves logs from the last terminated container, which is useful when a pod has already restarted. - -## Key Pods to Monitor - -| Pod | Purpose | -| --- | --- | -| `core-api` | Primary API server | -| `webapp` | Web application frontend | -| `connector-api` | Source connector service | -| `postgresql` | Relational data store | -| `clickhouse` | Analytics data store | -| `redis` | Session and cache store | - -:::warning -Frequent pod restarts caused by probe failures often indicate resource pressure (memory or CPU) rather than application bugs. Check node resource utilization with `kubectl top nodes` before investigating application-level issues. -::: diff --git a/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/_category_.json b/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/_category_.json deleted file mode 100644 index 53ae508120..0000000000 --- a/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Background Job Monitoring", - "position": 30, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "sidekiq" - } -} diff --git a/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/failedjobs.md b/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/failedjobs.md deleted file mode 100644 index b6749b9aa9..0000000000 --- a/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/failedjobs.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: "Failed Job Troubleshooting" -description: "Diagnosing and resolving failed background jobs" -sidebar_position: 30 ---- - -# Failed Job Troubleshooting - -When a Sidekiq background job encounters an error, it enters the retry cycle. Jobs that exhaust all retry attempts move to the dead set. This page explains how to find, diagnose, and resolve failed jobs. - -## Finding Failed Jobs - -Open the [Sidekiq Dashboard](/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/sidekiq) and navigate to the following tabs: - -- **Retries** -- Jobs that failed and are awaiting automatic retry. Each entry displays the error class, error message, and the number of retries attempted. -- **Dead** -- Jobs that exhausted all retry attempts. Dead jobs are not retried automatically and require manual action. - -## Retry Behavior - -Sidekiq uses an exponential backoff strategy for retries. The delay between retries increases with each attempt, following the formula: - -``` -(retry_count ^ 4) + 15 + (random(10) * (retry_count + 1)) seconds -``` - -By default, a job retries up to 25 times before being moved to the dead set. This means a failing job may continue retrying for approximately 21 days before it is considered dead. - -## Diagnosing Failures - -1. **Check the error message** in the Retries or Dead tab. The error class and message typically indicate the root cause (for example, a connection timeout or validation error). -2. **Review application logs** for the time of the failure: - -```bash -kubectl logs -n access-analyzer deploy/core-api --since=1h | grep -i error -``` - -3. **Check backing service health** -- Many job failures stem from database or Redis connectivity issues. See [Database Connectivity](/docs/accessanalyzer/1.0/troubleshooting/commonissues/databaseconnectivity). - -## Handling Dead Jobs - -From the **Dead** tab in the Sidekiq dashboard, you can: - -- **Retry** a specific dead job to re-enqueue it for processing. -- **Delete** a dead job to remove it permanently. -- **Retry All** to re-enqueue all dead jobs at once. - -:::warning -Before retrying dead jobs, ensure the underlying issue has been resolved. Retrying jobs without fixing the root cause will result in repeated failures. -::: - -## Common Failure Causes - -| Cause | Symptoms | Resolution | -| --- | --- | --- | -| Redis unavailable | All jobs fail simultaneously | Verify Redis pod health | -| Database timeout | Jobs in `scans` or `syncs` queues fail | Check PostgreSQL/ClickHouse connectivity | -| External API error | Connector-related jobs fail | Verify source credentials and network access | -| Memory pressure | Jobs killed mid-execution | Increase worker pod memory limits | diff --git a/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/queues.md b/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/queues.md deleted file mode 100644 index 3dc007d084..0000000000 --- a/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/queues.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: "Job Queues and Priorities" -description: "Understanding job queue structure and priority levels" -sidebar_position: 20 ---- - -# Job Queues and Priorities - -Access Analyzer processes background work through seven Sidekiq queues, each serving a specific purpose. Understanding queue roles and priorities helps you identify processing bottlenecks and backpressure. - -## Queue Overview - -| Queue | Priority | Purpose | -| --- | --- | --- | -| `critical` | Highest | System-critical operations that must complete promptly | -| `scans` | High | Data source scan execution | -| `syncs` | High | Data synchronization between sources and the platform | -| `scheduler` | Medium | Periodic task scheduling and orchestration | -| `default` | Medium | General-purpose background work | -| `mailers` | Low | Email notification delivery | -| `low` | Lowest | Deferred or non-urgent tasks | - -Sidekiq workers process queues in priority order. Higher-priority queues are drained before lower-priority ones. - -## Monitoring Queue Depth - -**From the Sidekiq dashboard**, navigate to the **Queues** tab to view the current size of each queue. A queue size that grows continuously indicates that jobs are being enqueued faster than workers can process them. - -**From the command line, query Prometheus for queue sizes:** - -```bash -kubectl exec -n access-analyzer deploy/prometheus -- \ - promtool query instant http://localhost:9090 'sidekiq_queue_size' -``` - -## Identifying Backpressure - -Backpressure occurs when one or more queues accumulate jobs faster than they are processed. Common causes include: - -- **Resource constraints** -- Insufficient CPU or memory on worker pods. Check with `kubectl top pods -n access-analyzer`. -- **Downstream dependency failures** -- Database or external service unavailability causing job retries and requeuing. -- **Large scan jobs** -- A scan targeting a large data source can consume worker capacity, delaying other queues. - -:::warning -If the `critical` queue has a sustained non-zero depth, investigate immediately. Delayed critical jobs can affect system stability and data consistency. -::: - -## Corrective Actions - -- Scale worker replicas if resource limits allow. -- Investigate and resolve downstream dependency failures (see [Database Connectivity](/docs/accessanalyzer/1.0/troubleshooting/commonissues/databaseconnectivity)). -- Stagger large scan jobs to avoid overwhelming worker capacity. diff --git a/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/sidekiq.md b/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/sidekiq.md deleted file mode 100644 index a7b43638c9..0000000000 --- a/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/sidekiq.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: "Sidekiq Dashboard" -description: "Monitoring background jobs via the Sidekiq web UI" -sidebar_position: 10 ---- - -# Sidekiq Dashboard - -Access Analyzer uses Sidekiq to process background jobs such as scans, syncs, and scheduled tasks. The Sidekiq web dashboard provides real-time visibility into job processing, queue health, and worker status. - -## Accessing the Dashboard - -The Sidekiq dashboard is available at the `/sidekiq` path on your Access Analyzer instance: - -``` -https:///sidekiq -``` - -The dashboard requires authentication. Enter the configured username and password when prompted. - -:::note -Dashboard credentials are set during installation. Contact your system administrator if you do not have the credentials. -::: - -## Dashboard Capabilities - -The Sidekiq web UI provides the following views: - -- **Dashboard** -- Real-time graph of processed and failed jobs over time. -- **Busy** -- Lists workers currently executing jobs, including the job class and arguments. -- **Queues** -- Displays all queues with their current size. Use this to identify backpressure. -- **Retries** -- Shows jobs that failed and are scheduled for automatic retry. -- **Scheduled** -- Lists jobs enqueued for future execution. -- **Dead** -- Contains jobs that exhausted all retry attempts. These require manual intervention. - -## Checking Job Throughput - -From the dashboard home page, review the **Processed** and **Failed** counters. A healthy system shows a steadily increasing processed count with a low or zero failed count. - -If the failed count is climbing, navigate to the **Retries** tab to inspect the error messages and determine the root cause. - -## Infrastructure Dependency - -Sidekiq depends on Redis for job storage and queue management. If the Sidekiq dashboard is unreachable or shows no data, verify that the Redis pod is running: - -```bash -kubectl get pods -n access-analyzer -l app=redis -``` - -See [Job Queues and Priorities](/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/queues) for details on individual queue behavior. diff --git a/docs/accessanalyzer/1.0/troubleshooting/observability/_category_.json b/docs/accessanalyzer/1.0/troubleshooting/observability/_category_.json deleted file mode 100644 index d6e5ecaf0a..0000000000 --- a/docs/accessanalyzer/1.0/troubleshooting/observability/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Observability", - "position": 20, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "opentelemetry" - } -} diff --git a/docs/accessanalyzer/1.0/troubleshooting/observability/opentelemetry.md b/docs/accessanalyzer/1.0/troubleshooting/observability/opentelemetry.md deleted file mode 100644 index d9d1ec28e6..0000000000 --- a/docs/accessanalyzer/1.0/troubleshooting/observability/opentelemetry.md +++ /dev/null @@ -1,76 +0,0 @@ ---- -title: "OpenTelemetry Traces and Metrics" -description: "Distributed tracing and metric collection" -sidebar_position: 10 ---- - -# OpenTelemetry Traces and Metrics - -Access Analyzer uses OpenTelemetry (OTel) for distributed tracing. Traces are collected by the `otel-collector` pod and stored in ClickHouse, allowing you to analyze request flows and identify performance bottlenecks. - -## Architecture - -Trace data flows through the following path: - -1. Application services instrument outgoing requests and operations with OTel spans. -2. The `otel-collector` pod receives spans and exports them to ClickHouse. -3. Traces are stored in the `access_analyzer_logs` database in ClickHouse. - -## Querying Traces in ClickHouse - -**Connect to the ClickHouse pod:** - -```bash -kubectl exec -it -n access-analyzer deploy/clickhouse -- clickhouse-client -``` - -**List available tables in the trace database:** - -```bash -USE access_analyzer_logs; -SHOW TABLES; -``` - -**Query recent traces by service name:** - -```bash -SELECT TraceId, SpanName, Duration, StatusCode -FROM otel_traces -WHERE ServiceName = 'core-api' -ORDER BY Timestamp DESC -LIMIT 20; -``` - -**Find slow spans exceeding a duration threshold (in nanoseconds):** - -```bash -SELECT TraceId, SpanName, Duration -FROM otel_traces -WHERE Duration > 5000000000 -ORDER BY Duration DESC -LIMIT 10; -``` - -## Common Trace Analysis - -- **High latency requests** -- Query for spans with long durations to identify slow database queries or external API calls. -- **Error spans** -- Filter by `StatusCode` to find spans that completed with errors. -- **Cross-service tracing** -- Use a `TraceId` to follow a request across `core-api`, `connector-api`, and backing services. - -## Verifying the OTel Collector - -**Check that the collector pod is running:** - -```bash -kubectl get pods -n access-analyzer -l app=otel-collector -``` - -**View collector logs for export errors:** - -```bash -kubectl logs -n access-analyzer deploy/otel-collector --tail=50 -``` - -:::note -Trace retention depends on your ClickHouse storage configuration. Monitor disk usage on the ClickHouse pod to ensure traces are not consuming excessive storage. -::: diff --git a/docs/accessanalyzer/1.0/troubleshooting/observability/prometheus.md b/docs/accessanalyzer/1.0/troubleshooting/observability/prometheus.md deleted file mode 100644 index 253f2f8b3a..0000000000 --- a/docs/accessanalyzer/1.0/troubleshooting/observability/prometheus.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: "Prometheus Monitoring" -description: "Prometheus metrics and alerting" -sidebar_position: 20 ---- - -# Prometheus Monitoring - -Access Analyzer includes a Prometheus instance that collects metrics from application services and infrastructure components. Use Prometheus to monitor resource utilization, request rates, and application performance. - -## Accessing Prometheus - -The Prometheus pod runs in the `access-analyzer` namespace. To access the Prometheus web UI, set up a port forward: - -```bash -kubectl port-forward -n access-analyzer deploy/prometheus 9090:9090 -``` - -Then open `http://localhost:9090` in your browser. - -## Key Metrics to Monitor - -| Metric | Description | -| --- | --- | -| `container_memory_usage_bytes` | Memory consumption per container | -| `container_cpu_usage_seconds_total` | CPU usage per container | -| `http_request_duration_seconds` | Request latency histogram | -| `http_requests_total` | Total request count by status code | -| `sidekiq_queue_size` | Number of jobs waiting in each Sidekiq queue | -| `pg_stat_activity_count` | Active PostgreSQL connections | - -## Useful PromQL Queries - -**Check memory usage for Access Analyzer pods:** - -```bash -container_memory_usage_bytes{namespace="access-analyzer"} -``` - -**Calculate request error rate over the last 5 minutes:** - -```bash -rate(http_requests_total{namespace="access-analyzer", status=~"5.."}[5m]) -``` - -**Monitor Sidekiq queue depth:** - -```bash -sidekiq_queue_size{namespace="access-analyzer"} -``` - -## Recording Rules - -Access Analyzer ships with Prometheus recording rules that pre-compute frequently used metric aggregations. Recording rules reduce query latency for dashboards and alerts. View the active recording rules in the Prometheus UI under **Status > Rules**. - -## Verifying Prometheus Health - -**Confirm the Prometheus pod is running:** - -```bash -kubectl get pods -n access-analyzer -l app=prometheus -``` - -**Check Prometheus targets to ensure all scrape endpoints are reachable:** - -Open `http://localhost:9090/targets` (with port forward active) and verify all targets show an **UP** state. - -:::warning -If Prometheus targets appear as **DOWN**, verify that the target pods are running and that network policies allow traffic from the Prometheus pod on the metrics port. -::: diff --git a/docs/accessanalyzer/1.0/troubleshooting/overview.md b/docs/accessanalyzer/1.0/troubleshooting/overview.md deleted file mode 100644 index 806ed1a446..0000000000 --- a/docs/accessanalyzer/1.0/troubleshooting/overview.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: "Monitoring and Troubleshooting" -description: "Health checks, observability, and common issue resolution" -sidebar_position: 1 ---- - -# Monitoring and Troubleshooting - -This section provides guidance for monitoring the health of your Netwrix Access Analyzer deployment and resolving common issues. Use the categories below to navigate to the relevant topic. - -## Troubleshooting Categories - -| Category | Description | Link | -| --- | --- | --- | -| Health Checks | Kubernetes probes and service health endpoints | [Probes](/docs/accessanalyzer/1.0/troubleshooting/healthchecks/probes), [Endpoints](/docs/accessanalyzer/1.0/troubleshooting/healthchecks/endpoints) | -| Observability | Distributed tracing and metrics collection | [OpenTelemetry](/docs/accessanalyzer/1.0/troubleshooting/observability/opentelemetry), [Prometheus](/docs/accessanalyzer/1.0/troubleshooting/observability/prometheus) | -| Job Monitoring | Background job processing and queue health | [Sidekiq](/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/sidekiq), [Queues](/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/queues), [Failed Jobs](/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/failedjobs) | -| Common Issues | Connection failures, scan errors, and database connectivity | [Connections](/docs/accessanalyzer/1.0/troubleshooting/commonissues/connectionfailures), [Scans](/docs/accessanalyzer/1.0/troubleshooting/commonissues/scanerrors), [Database](/docs/accessanalyzer/1.0/troubleshooting/commonissues/databaseconnectivity) | - -## Quick Diagnostic Commands - -Run the following commands to get an immediate overview of system health. - -**Check all pod status across namespaces:** - -```bash -kubectl get pods -A -``` - -**View resource consumption for nodes and pods:** - -```bash -kubectl top nodes -kubectl top pods -n access-analyzer -``` - -**Check ArgoCD application sync status:** - -```bash -kubectl get apps -n argocd -``` - -**View logs for a specific pod:** - -```bash -kubectl logs -n access-analyzer --tail=100 -``` - -**Review installer and preflight logs:** - -```bash -cat /var/log/dspm-installer.log -cat /var/log/dspm-preflight.json -``` - -## Installer Exit Codes - -If installation failed, check the exit code to identify the failure category. - -| Exit Code | Meaning | -| --- | --- | -| 10 | License validation failure | -| 50 | K3s installation or startup failure | -| 60 | ArgoCD deployment failure | -| 70 | Application readiness timeout | -| 80 | Preflight check failure (CPU, memory, disk, kernel, or cgroups) | - -:::note -Most troubleshooting commands require `kubectl` access to the cluster. Ensure your kubeconfig is configured correctly before running diagnostics. -::: From 1bd992bdd5ff8f6fb860f08090f4b8057d1fdc2f Mon Sep 17 00:00:00 2001 From: carlos-mejia_nwx Date: Thu, 19 Mar 2026 23:38:57 -0400 Subject: [PATCH 03/62] =?UTF-8?q?AA26:=20Complete=20documentation=20outlin?= =?UTF-8?q?e=20=E2=80=94=2010=20top-level=20sections=20with=20subsections?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restructured v1.0 docs from nested Overview into flat top-level sections: Overview, System Requirements, Connector Requirements, Installation, Start Collecting Data, Configurations, Utilizing Scanners, Dashboards, Reports, and Activity Monitor Integration. All pages contain placeholder content for outline review. Co-Authored-By: Claude Opus 4.6 --- .../_category_.json | 6 + .../activity-monitor-integration/overview.md | 9 ++ .../1.0/configurations/_category_.json | 6 + .../configuration-node/_category_.json | 6 + .../application-settings.md | 9 ++ .../configurations/configuration-node/logs.md | 9 ++ .../configuration-node/scan-executions.md | 9 ++ .../configuration-node/scans.md | 9 ++ .../configuration-node/sensitive-data.md | 9 ++ .../configuration-node/service-accounts.md | 9 ++ .../configuration-node/source-groups.md | 9 ++ .../configuration-node/sources.md | 9 ++ .../configuration-node/users.md | 9 ++ .../configurations/mip-labeling-workflow.md | 9 ++ .../source-group-changes/_category_.json | 6 + .../source-group-changes/active-directory.md | 9 ++ .../source-group-changes/entra-id.md | 9 ++ .../source-group-changes/file-server.md | 9 ++ .../source-group-changes/sharepoint-online.md | 9 ++ .../connectors/_category_.json | 2 +- .../connectors/activedirectory.md | 0 .../requirements => }/connectors/cifs.md | 0 .../1.0/connectors/entra-id/_category_.json | 6 + .../entra-id/app-registration-secret.md | 9 ++ .../connectors/entra-id/entra-requirements.md | 9 ++ .../entra-id/overview.md} | 0 .../1.0/connectors/file-servers.md | 9 ++ .../sharepoint-online/_category_.json | 6 + .../sharepoint-online/azure-permissions.md | 9 ++ .../tenant-certificate-config.md | 9 ++ .../1.0/dashboards-overview/_category_.json | 6 + .../_category_.json | 6 + .../data-security-dashboard/_category_.json | 6 + .../data-security-dashboard/activity.md | 9 ++ .../data-security-dashboard/overview.md | 9 ++ .../how-to-analyze-the-data.md | 9 ++ .../1.0/gettingstarted/_category_.json | 6 + .../gettingstarted/active-directory-sync.md | 9 ++ .../activity-data/_category_.json | 6 + .../activity-data/file-server-activity.md | 9 ++ .../1.0/gettingstarted/entra-id-sync.md | 9 ++ .../1.0/gettingstarted/file-server-scans.md | 9 ++ .../gettingstarted/first-service-account.md | 9 ++ .../gettingstarted/sharepoint-online-scan.md | 9 ++ .../1.0/gettingstarted/source-group-wizard.md | 9 ++ docs/accessanalyzer/1.0/index.md | 1 + .../{overview => }/install/_category_.json | 2 +- .../1.0/{overview => }/install/postinstall.md | 0 .../{overview => }/install/quickinstall.md | 0 .../1.0/{overview => }/install/security.md | 0 .../1.0/{overview => }/install/uninstall.md | 0 .../1.0/overview/_category_.json | 6 +- .../1.0/overview/install/dspmctl.md | 141 ---------------- .../overview/install/environmentvariables.md | 92 ----------- .../1.0/overview/install/network.md | 96 ----------- .../1.0/overview/install/overview.md | 49 ------ .../1.0/overview/install/preflight.md | 111 ------------- .../1.0/overview/install/ssl.md | 56 ------- .../1.0/overview/install/stepbystep.md | 150 ------------------ .../1.0/overview/install/upgrade.md | 77 --------- docs/accessanalyzer/1.0/overview/overview.md | 36 ----- .../1.0/overview/requirements/_category_.json | 10 -- .../requirements/connectors/localgroups.md | 52 ------ .../connectors/sharepointonline.md | 57 ------- .../requirements/database/_category_.json | 10 -- .../requirements/database/clickhouse.md | 30 ---- .../requirements/database/postgresql.md | 40 ----- .../overview/requirements/database/redis.md | 43 ----- .../1.0/overview/requirements/overview.md | 35 ---- .../overview/requirements/system/hardware.md | 84 ---------- .../1.0/reports-overview/_category_.json | 6 + .../1.0/reports-overview/access.md | 9 ++ .../1.0/reports-overview/activity.md | 9 ++ .../1.0/reports-overview/content.md | 9 ++ .../how-to-analyze-the-data.md | 9 ++ .../1.0/reports-overview/my-reports.md | 9 ++ .../1.0/reports-overview/sensitive-data.md | 9 ++ .../1.0/scanners/_category_.json | 6 + docs/accessanalyzer/1.0/scanners/overview.md | 9 ++ .../requirements => }/system/_category_.json | 2 +- .../requirements => }/system/kubernetes.md | 0 .../requirements => }/system/network.md | 0 .../install => system}/requirements.md | 0 83 files changed, 416 insertions(+), 1177 deletions(-) create mode 100644 docs/accessanalyzer/1.0/activity-monitor-integration/_category_.json create mode 100644 docs/accessanalyzer/1.0/activity-monitor-integration/overview.md create mode 100644 docs/accessanalyzer/1.0/configurations/_category_.json create mode 100644 docs/accessanalyzer/1.0/configurations/configuration-node/_category_.json create mode 100644 docs/accessanalyzer/1.0/configurations/configuration-node/application-settings.md create mode 100644 docs/accessanalyzer/1.0/configurations/configuration-node/logs.md create mode 100644 docs/accessanalyzer/1.0/configurations/configuration-node/scan-executions.md create mode 100644 docs/accessanalyzer/1.0/configurations/configuration-node/scans.md create mode 100644 docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data.md create mode 100644 docs/accessanalyzer/1.0/configurations/configuration-node/service-accounts.md create mode 100644 docs/accessanalyzer/1.0/configurations/configuration-node/source-groups.md create mode 100644 docs/accessanalyzer/1.0/configurations/configuration-node/sources.md create mode 100644 docs/accessanalyzer/1.0/configurations/configuration-node/users.md create mode 100644 docs/accessanalyzer/1.0/configurations/mip-labeling-workflow.md create mode 100644 docs/accessanalyzer/1.0/configurations/source-group-changes/_category_.json create mode 100644 docs/accessanalyzer/1.0/configurations/source-group-changes/active-directory.md create mode 100644 docs/accessanalyzer/1.0/configurations/source-group-changes/entra-id.md create mode 100644 docs/accessanalyzer/1.0/configurations/source-group-changes/file-server.md create mode 100644 docs/accessanalyzer/1.0/configurations/source-group-changes/sharepoint-online.md rename docs/accessanalyzer/1.0/{overview/requirements => }/connectors/_category_.json (88%) rename docs/accessanalyzer/1.0/{overview/requirements => }/connectors/activedirectory.md (100%) rename docs/accessanalyzer/1.0/{overview/requirements => }/connectors/cifs.md (100%) create mode 100644 docs/accessanalyzer/1.0/connectors/entra-id/_category_.json create mode 100644 docs/accessanalyzer/1.0/connectors/entra-id/app-registration-secret.md create mode 100644 docs/accessanalyzer/1.0/connectors/entra-id/entra-requirements.md rename docs/accessanalyzer/1.0/{overview/requirements/connectors/entraid.md => connectors/entra-id/overview.md} (100%) create mode 100644 docs/accessanalyzer/1.0/connectors/file-servers.md create mode 100644 docs/accessanalyzer/1.0/connectors/sharepoint-online/_category_.json create mode 100644 docs/accessanalyzer/1.0/connectors/sharepoint-online/azure-permissions.md create mode 100644 docs/accessanalyzer/1.0/connectors/sharepoint-online/tenant-certificate-config.md create mode 100644 docs/accessanalyzer/1.0/dashboards-overview/_category_.json create mode 100644 docs/accessanalyzer/1.0/dashboards-overview/active-directory-dashboard/_category_.json create mode 100644 docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/_category_.json create mode 100644 docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/activity.md create mode 100644 docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/overview.md create mode 100644 docs/accessanalyzer/1.0/dashboards-overview/how-to-analyze-the-data.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/_category_.json create mode 100644 docs/accessanalyzer/1.0/gettingstarted/active-directory-sync.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/activity-data/_category_.json create mode 100644 docs/accessanalyzer/1.0/gettingstarted/activity-data/file-server-activity.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/entra-id-sync.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/file-server-scans.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/first-service-account.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/source-group-wizard.md rename docs/accessanalyzer/1.0/{overview => }/install/_category_.json (80%) rename docs/accessanalyzer/1.0/{overview => }/install/postinstall.md (100%) rename docs/accessanalyzer/1.0/{overview => }/install/quickinstall.md (100%) rename docs/accessanalyzer/1.0/{overview => }/install/security.md (100%) rename docs/accessanalyzer/1.0/{overview => }/install/uninstall.md (100%) delete mode 100644 docs/accessanalyzer/1.0/overview/install/dspmctl.md delete mode 100644 docs/accessanalyzer/1.0/overview/install/environmentvariables.md delete mode 100644 docs/accessanalyzer/1.0/overview/install/network.md delete mode 100644 docs/accessanalyzer/1.0/overview/install/overview.md delete mode 100644 docs/accessanalyzer/1.0/overview/install/preflight.md delete mode 100644 docs/accessanalyzer/1.0/overview/install/ssl.md delete mode 100644 docs/accessanalyzer/1.0/overview/install/stepbystep.md delete mode 100644 docs/accessanalyzer/1.0/overview/install/upgrade.md delete mode 100644 docs/accessanalyzer/1.0/overview/overview.md delete mode 100644 docs/accessanalyzer/1.0/overview/requirements/_category_.json delete mode 100644 docs/accessanalyzer/1.0/overview/requirements/connectors/localgroups.md delete mode 100644 docs/accessanalyzer/1.0/overview/requirements/connectors/sharepointonline.md delete mode 100644 docs/accessanalyzer/1.0/overview/requirements/database/_category_.json delete mode 100644 docs/accessanalyzer/1.0/overview/requirements/database/clickhouse.md delete mode 100644 docs/accessanalyzer/1.0/overview/requirements/database/postgresql.md delete mode 100644 docs/accessanalyzer/1.0/overview/requirements/database/redis.md delete mode 100644 docs/accessanalyzer/1.0/overview/requirements/overview.md delete mode 100644 docs/accessanalyzer/1.0/overview/requirements/system/hardware.md create mode 100644 docs/accessanalyzer/1.0/reports-overview/_category_.json create mode 100644 docs/accessanalyzer/1.0/reports-overview/access.md create mode 100644 docs/accessanalyzer/1.0/reports-overview/activity.md create mode 100644 docs/accessanalyzer/1.0/reports-overview/content.md create mode 100644 docs/accessanalyzer/1.0/reports-overview/how-to-analyze-the-data.md create mode 100644 docs/accessanalyzer/1.0/reports-overview/my-reports.md create mode 100644 docs/accessanalyzer/1.0/reports-overview/sensitive-data.md create mode 100644 docs/accessanalyzer/1.0/scanners/_category_.json create mode 100644 docs/accessanalyzer/1.0/scanners/overview.md rename docs/accessanalyzer/1.0/{overview/requirements => }/system/_category_.json (88%) rename docs/accessanalyzer/1.0/{overview/requirements => }/system/kubernetes.md (100%) rename docs/accessanalyzer/1.0/{overview/requirements => }/system/network.md (100%) rename docs/accessanalyzer/1.0/{overview/install => system}/requirements.md (100%) diff --git a/docs/accessanalyzer/1.0/activity-monitor-integration/_category_.json b/docs/accessanalyzer/1.0/activity-monitor-integration/_category_.json new file mode 100644 index 0000000000..463f554a78 --- /dev/null +++ b/docs/accessanalyzer/1.0/activity-monitor-integration/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Setting up Activity Monitor Integration", + "position": 70, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/activity-monitor-integration/overview.md b/docs/accessanalyzer/1.0/activity-monitor-integration/overview.md new file mode 100644 index 0000000000..21dd6869e7 --- /dev/null +++ b/docs/accessanalyzer/1.0/activity-monitor-integration/overview.md @@ -0,0 +1,9 @@ +--- +title: "Setting up Activity Monitor Integration" +description: "Configure Activity Monitor integration with Access Analyzer" +sidebar_position: 10 +--- + +# Setting up Activity Monitor Integration + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/_category_.json b/docs/accessanalyzer/1.0/configurations/_category_.json new file mode 100644 index 0000000000..9b86fef70b --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Configurations and Making Changes", + "position": 30, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/_category_.json b/docs/accessanalyzer/1.0/configurations/configuration-node/_category_.json new file mode 100644 index 0000000000..d5bca8fd28 --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Configuration Node", + "position": 20, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/application-settings.md b/docs/accessanalyzer/1.0/configurations/configuration-node/application-settings.md new file mode 100644 index 0000000000..3aba566106 --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/application-settings.md @@ -0,0 +1,9 @@ +--- +title: "Application Settings" +description: "Managing application settings in the Configuration node" +sidebar_position: 60 +--- + +# Application Settings + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/logs.md b/docs/accessanalyzer/1.0/configurations/configuration-node/logs.md new file mode 100644 index 0000000000..b28fd89fbe --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/logs.md @@ -0,0 +1,9 @@ +--- +title: "Logs" +description: "Viewing logs in the Configuration node" +sidebar_position: 70 +--- + +# Logs + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/scan-executions.md b/docs/accessanalyzer/1.0/configurations/configuration-node/scan-executions.md new file mode 100644 index 0000000000..d2f01e283b --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/scan-executions.md @@ -0,0 +1,9 @@ +--- +title: "Scan Executions" +description: "Viewing scan execution history in the Configuration node" +sidebar_position: 40 +--- + +# Scan Executions + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/scans.md b/docs/accessanalyzer/1.0/configurations/configuration-node/scans.md new file mode 100644 index 0000000000..0f21da4b92 --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/scans.md @@ -0,0 +1,9 @@ +--- +title: "Scans" +description: "Managing scans in the Configuration node" +sidebar_position: 30 +--- + +# Scans + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data.md b/docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data.md new file mode 100644 index 0000000000..5c5453e455 --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data.md @@ -0,0 +1,9 @@ +--- +title: "Sensitive Data" +description: "Managing sensitive data settings in the Configuration node" +sidebar_position: 55 +--- + +# Sensitive Data + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/service-accounts.md b/docs/accessanalyzer/1.0/configurations/configuration-node/service-accounts.md new file mode 100644 index 0000000000..7ce3e52660 --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/service-accounts.md @@ -0,0 +1,9 @@ +--- +title: "Service Accounts" +description: "Managing service accounts in the Configuration node" +sidebar_position: 20 +--- + +# Service Accounts + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/source-groups.md b/docs/accessanalyzer/1.0/configurations/configuration-node/source-groups.md new file mode 100644 index 0000000000..d78d64468a --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/source-groups.md @@ -0,0 +1,9 @@ +--- +title: "Source Groups" +description: "Managing source groups in the Configuration node" +sidebar_position: 80 +--- + +# Source Groups + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/sources.md b/docs/accessanalyzer/1.0/configurations/configuration-node/sources.md new file mode 100644 index 0000000000..f99a43aef2 --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/sources.md @@ -0,0 +1,9 @@ +--- +title: "Sources" +description: "Managing sources in the Configuration node" +sidebar_position: 10 +--- + +# Sources + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/users.md b/docs/accessanalyzer/1.0/configurations/configuration-node/users.md new file mode 100644 index 0000000000..c5a0e8191a --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/users.md @@ -0,0 +1,9 @@ +--- +title: "Users" +description: "Managing users in the Configuration node" +sidebar_position: 50 +--- + +# Users + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/mip-labeling-workflow.md b/docs/accessanalyzer/1.0/configurations/mip-labeling-workflow.md new file mode 100644 index 0000000000..b28cbd75aa --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/mip-labeling-workflow.md @@ -0,0 +1,9 @@ +--- +title: "MIP Labeling and Workflow" +description: "Microsoft Information Protection labeling and workflow configuration" +sidebar_position: 30 +--- + +# MIP Labeling and Workflow + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/source-group-changes/_category_.json b/docs/accessanalyzer/1.0/configurations/source-group-changes/_category_.json new file mode 100644 index 0000000000..0b5c8adf0b --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/source-group-changes/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Making Changes to Source Group Wizards", + "position": 10, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/configurations/source-group-changes/active-directory.md b/docs/accessanalyzer/1.0/configurations/source-group-changes/active-directory.md new file mode 100644 index 0000000000..f723d5e4a8 --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/source-group-changes/active-directory.md @@ -0,0 +1,9 @@ +--- +title: "Active Directory Source Group" +description: "Making changes to an Active Directory source group wizard workflow" +sidebar_position: 10 +--- + +# Active Directory Source Group + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/source-group-changes/entra-id.md b/docs/accessanalyzer/1.0/configurations/source-group-changes/entra-id.md new file mode 100644 index 0000000000..787bb89c41 --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/source-group-changes/entra-id.md @@ -0,0 +1,9 @@ +--- +title: "Entra ID Source Group" +description: "Making changes to an Entra ID source group wizard workflow" +sidebar_position: 30 +--- + +# Entra ID Source Group + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/source-group-changes/file-server.md b/docs/accessanalyzer/1.0/configurations/source-group-changes/file-server.md new file mode 100644 index 0000000000..7186761125 --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/source-group-changes/file-server.md @@ -0,0 +1,9 @@ +--- +title: "File Server Source Group" +description: "Making changes to a File Server source group wizard workflow" +sidebar_position: 20 +--- + +# File Server Source Group + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/source-group-changes/sharepoint-online.md b/docs/accessanalyzer/1.0/configurations/source-group-changes/sharepoint-online.md new file mode 100644 index 0000000000..0b81d403ff --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/source-group-changes/sharepoint-online.md @@ -0,0 +1,9 @@ +--- +title: "SharePoint Online Source Group" +description: "Making changes to a SharePoint Online source group wizard workflow" +sidebar_position: 40 +--- + +# SharePoint Online Source Group + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/overview/requirements/connectors/_category_.json b/docs/accessanalyzer/1.0/connectors/_category_.json similarity index 88% rename from docs/accessanalyzer/1.0/overview/requirements/connectors/_category_.json rename to docs/accessanalyzer/1.0/connectors/_category_.json index 4616c42c8c..4ebd7ecb5d 100644 --- a/docs/accessanalyzer/1.0/overview/requirements/connectors/_category_.json +++ b/docs/accessanalyzer/1.0/connectors/_category_.json @@ -1,6 +1,6 @@ { "label": "Connector Requirements", - "position": 30, + "position": 14, "collapsed": true, "collapsible": true, "link": { diff --git a/docs/accessanalyzer/1.0/overview/requirements/connectors/activedirectory.md b/docs/accessanalyzer/1.0/connectors/activedirectory.md similarity index 100% rename from docs/accessanalyzer/1.0/overview/requirements/connectors/activedirectory.md rename to docs/accessanalyzer/1.0/connectors/activedirectory.md diff --git a/docs/accessanalyzer/1.0/overview/requirements/connectors/cifs.md b/docs/accessanalyzer/1.0/connectors/cifs.md similarity index 100% rename from docs/accessanalyzer/1.0/overview/requirements/connectors/cifs.md rename to docs/accessanalyzer/1.0/connectors/cifs.md diff --git a/docs/accessanalyzer/1.0/connectors/entra-id/_category_.json b/docs/accessanalyzer/1.0/connectors/entra-id/_category_.json new file mode 100644 index 0000000000..83c1bf103d --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/entra-id/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Entra ID", + "position": 30, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/connectors/entra-id/app-registration-secret.md b/docs/accessanalyzer/1.0/connectors/entra-id/app-registration-secret.md new file mode 100644 index 0000000000..789a141560 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/entra-id/app-registration-secret.md @@ -0,0 +1,9 @@ +--- +title: "App Registration / Secret Configuration" +description: "Configure app registration and client secret for Entra ID" +sidebar_position: 30 +--- + +# App Registration / Secret Configuration + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/connectors/entra-id/entra-requirements.md b/docs/accessanalyzer/1.0/connectors/entra-id/entra-requirements.md new file mode 100644 index 0000000000..b2b3c7917a --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/entra-id/entra-requirements.md @@ -0,0 +1,9 @@ +--- +title: "Setting Up Requirements Within Entra" +description: "Configure Entra ID requirements for connectivity" +sidebar_position: 20 +--- + +# Setting Up Requirements Within Entra + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/overview/requirements/connectors/entraid.md b/docs/accessanalyzer/1.0/connectors/entra-id/overview.md similarity index 100% rename from docs/accessanalyzer/1.0/overview/requirements/connectors/entraid.md rename to docs/accessanalyzer/1.0/connectors/entra-id/overview.md diff --git a/docs/accessanalyzer/1.0/connectors/file-servers.md b/docs/accessanalyzer/1.0/connectors/file-servers.md new file mode 100644 index 0000000000..a70313521e --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/file-servers.md @@ -0,0 +1,9 @@ +--- +title: "File Servers" +description: "File server connector requirements for Access Analyzer" +sidebar_position: 20 +--- + +# File Servers + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/connectors/sharepoint-online/_category_.json b/docs/accessanalyzer/1.0/connectors/sharepoint-online/_category_.json new file mode 100644 index 0000000000..a8d05dd13b --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/sharepoint-online/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "SharePoint Online", + "position": 50, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/connectors/sharepoint-online/azure-permissions.md b/docs/accessanalyzer/1.0/connectors/sharepoint-online/azure-permissions.md new file mode 100644 index 0000000000..da88304a7a --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/sharepoint-online/azure-permissions.md @@ -0,0 +1,9 @@ +--- +title: "Setting Up Requirements Within Entra" +description: "Configure Entra ID requirements for SharePoint Online connectivity" +sidebar_position: 10 +--- + +# Setting Up Requirements Within Entra + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/connectors/sharepoint-online/tenant-certificate-config.md b/docs/accessanalyzer/1.0/connectors/sharepoint-online/tenant-certificate-config.md new file mode 100644 index 0000000000..b702b388e5 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/sharepoint-online/tenant-certificate-config.md @@ -0,0 +1,9 @@ +--- +title: "App Registration / Certificate Configuration" +description: "Configure app registration and certificate authentication for SharePoint Online" +sidebar_position: 20 +--- + +# App Registration / Certificate Configuration + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/dashboards-overview/_category_.json b/docs/accessanalyzer/1.0/dashboards-overview/_category_.json new file mode 100644 index 0000000000..2ce5a39907 --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards-overview/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Dashboards Overview", + "position": 50, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/dashboards-overview/active-directory-dashboard/_category_.json b/docs/accessanalyzer/1.0/dashboards-overview/active-directory-dashboard/_category_.json new file mode 100644 index 0000000000..527eda587f --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards-overview/active-directory-dashboard/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Active Directory Dashboard", + "position": 30, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/_category_.json b/docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/_category_.json new file mode 100644 index 0000000000..d27cd7ee77 --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Data Security Dashboard", + "position": 20, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/activity.md b/docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/activity.md new file mode 100644 index 0000000000..cd6072b460 --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/activity.md @@ -0,0 +1,9 @@ +--- +title: "Activity" +description: "Activity view in the Data Security Dashboard" +sidebar_position: 20 +--- + +# Activity + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/overview.md b/docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/overview.md new file mode 100644 index 0000000000..c6d4d8bd09 --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/overview.md @@ -0,0 +1,9 @@ +--- +title: "Overview" +description: "Overview of the Data Security Dashboard" +sidebar_position: 10 +--- + +# Overview + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/dashboards-overview/how-to-analyze-the-data.md b/docs/accessanalyzer/1.0/dashboards-overview/how-to-analyze-the-data.md new file mode 100644 index 0000000000..dfb66b947e --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards-overview/how-to-analyze-the-data.md @@ -0,0 +1,9 @@ +--- +title: "How to Analyze the Data" +description: "Learn how to analyze data presented in dashboards" +sidebar_position: 10 +--- + +# How to Analyze the Data + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/gettingstarted/_category_.json b/docs/accessanalyzer/1.0/gettingstarted/_category_.json new file mode 100644 index 0000000000..1c9c947f1d --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Start Collecting Data", + "position": 20, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/gettingstarted/active-directory-sync.md b/docs/accessanalyzer/1.0/gettingstarted/active-directory-sync.md new file mode 100644 index 0000000000..55ac39164a --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/active-directory-sync.md @@ -0,0 +1,9 @@ +--- +title: "Setting Up My First Active Directory Sync" +description: "Connect to Active Directory and sync users, groups, and organizational units" +sidebar_position: 20 +--- + +# Setting Up My First Active Directory Sync + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/gettingstarted/activity-data/_category_.json b/docs/accessanalyzer/1.0/gettingstarted/activity-data/_category_.json new file mode 100644 index 0000000000..188fff07b8 --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/activity-data/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Start Collecting Activity Data", + "position": 70, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/gettingstarted/activity-data/file-server-activity.md b/docs/accessanalyzer/1.0/gettingstarted/activity-data/file-server-activity.md new file mode 100644 index 0000000000..41114e0caa --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/activity-data/file-server-activity.md @@ -0,0 +1,9 @@ +--- +title: "File Server Activity" +description: "Start collecting file server activity data" +sidebar_position: 10 +--- + +# File Server Activity + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/gettingstarted/entra-id-sync.md b/docs/accessanalyzer/1.0/gettingstarted/entra-id-sync.md new file mode 100644 index 0000000000..031773a286 --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/entra-id-sync.md @@ -0,0 +1,9 @@ +--- +title: "Setting Up My First Entra ID Sync" +description: "Connect to Microsoft Entra ID and sync cloud identities" +sidebar_position: 40 +--- + +# Setting Up My First Entra ID Sync + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/gettingstarted/file-server-scans.md b/docs/accessanalyzer/1.0/gettingstarted/file-server-scans.md new file mode 100644 index 0000000000..e99a39cb05 --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/file-server-scans.md @@ -0,0 +1,9 @@ +--- +title: "Setting Up My First File Server Scans" +description: "Scan CIFS/SMB file shares for permissions and sensitive data" +sidebar_position: 30 +--- + +# Setting Up My First File Server Scans + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/gettingstarted/first-service-account.md b/docs/accessanalyzer/1.0/gettingstarted/first-service-account.md new file mode 100644 index 0000000000..124d4ff6bb --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/first-service-account.md @@ -0,0 +1,9 @@ +--- +title: "Setting Up My First Service Account" +description: "Create your first service account to connect to data sources" +sidebar_position: 1 +--- + +# Setting Up My First Service Account + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan.md b/docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan.md new file mode 100644 index 0000000000..e831c710c1 --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan.md @@ -0,0 +1,9 @@ +--- +title: "Setting Up My First SharePoint Online Scan" +description: "Scan SharePoint Online sites for permissions and sensitive data" +sidebar_position: 50 +--- + +# Setting Up My First SharePoint Online Scan + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/gettingstarted/source-group-wizard.md b/docs/accessanalyzer/1.0/gettingstarted/source-group-wizard.md new file mode 100644 index 0000000000..a78450039d --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/source-group-wizard.md @@ -0,0 +1,9 @@ +--- +title: "Understanding the Source Group Wizard Workflow" +description: "Learn how the Source Group Wizard guides you through connecting data sources and configuring scans" +sidebar_position: 10 +--- + +# Understanding the Source Group Wizard Workflow + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/index.md b/docs/accessanalyzer/1.0/index.md index 854bbb7dbe..f9ad0c684b 100644 --- a/docs/accessanalyzer/1.0/index.md +++ b/docs/accessanalyzer/1.0/index.md @@ -18,3 +18,4 @@ Netwrix Access Analyzer is an on-premises Data Security Posture Management (DSPM ## Documentation Sections - [Overview](overview/overview) — Introduction to the product, key concepts, requirements, and installation +- [Getting Started](gettingstarted/overview) — Step-by-step guides for your first scans and syncs diff --git a/docs/accessanalyzer/1.0/overview/install/_category_.json b/docs/accessanalyzer/1.0/install/_category_.json similarity index 80% rename from docs/accessanalyzer/1.0/overview/install/_category_.json rename to docs/accessanalyzer/1.0/install/_category_.json index f5134e8f2b..edb97672cd 100644 --- a/docs/accessanalyzer/1.0/overview/install/_category_.json +++ b/docs/accessanalyzer/1.0/install/_category_.json @@ -1,6 +1,6 @@ { "label": "Installation", - "position": 40, + "position": 16, "collapsed": true, "collapsible": true } diff --git a/docs/accessanalyzer/1.0/overview/install/postinstall.md b/docs/accessanalyzer/1.0/install/postinstall.md similarity index 100% rename from docs/accessanalyzer/1.0/overview/install/postinstall.md rename to docs/accessanalyzer/1.0/install/postinstall.md diff --git a/docs/accessanalyzer/1.0/overview/install/quickinstall.md b/docs/accessanalyzer/1.0/install/quickinstall.md similarity index 100% rename from docs/accessanalyzer/1.0/overview/install/quickinstall.md rename to docs/accessanalyzer/1.0/install/quickinstall.md diff --git a/docs/accessanalyzer/1.0/overview/install/security.md b/docs/accessanalyzer/1.0/install/security.md similarity index 100% rename from docs/accessanalyzer/1.0/overview/install/security.md rename to docs/accessanalyzer/1.0/install/security.md diff --git a/docs/accessanalyzer/1.0/overview/install/uninstall.md b/docs/accessanalyzer/1.0/install/uninstall.md similarity index 100% rename from docs/accessanalyzer/1.0/overview/install/uninstall.md rename to docs/accessanalyzer/1.0/install/uninstall.md diff --git a/docs/accessanalyzer/1.0/overview/_category_.json b/docs/accessanalyzer/1.0/overview/_category_.json index 5015c8e965..e030b69dcf 100644 --- a/docs/accessanalyzer/1.0/overview/_category_.json +++ b/docs/accessanalyzer/1.0/overview/_category_.json @@ -2,9 +2,5 @@ "label": "Overview", "position": 10, "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } + "collapsible": true } diff --git a/docs/accessanalyzer/1.0/overview/install/dspmctl.md b/docs/accessanalyzer/1.0/overview/install/dspmctl.md deleted file mode 100644 index 7bdc4cc594..0000000000 --- a/docs/accessanalyzer/1.0/overview/install/dspmctl.md +++ /dev/null @@ -1,141 +0,0 @@ ---- -title: "DSPMctl CLI" -description: "Command-line reference for the DSPMctl application management tool" -sidebar_position: 45 ---- - -# DSPMctl CLI - -DSPMctl is a command-line tool installed by the Access Analyzer installer at `/usr/local/bin/dspmctl`. It provides convenient commands for managing ArgoCD-deployed applications without requiring direct `kubectl` or ArgoCD CLI interaction. - -## Commands - -### auto-status - -Display the current sync and auto-sync status of all applications: - -```bash -dspmctl auto-status -``` - -### enable-auto - -Enable auto-sync for a specific application. When auto-sync is enabled, ArgoCD automatically applies changes when the target revision is updated in the OCI registry: - -```bash -dspmctl enable-auto -``` - -**Example:** - -```bash -dspmctl enable-auto netwrix.core-api -``` - -### disable-auto - -Disable auto-sync for a specific application: - -```bash -dspmctl disable-auto -``` - -### set-revision - -Update the target revision (version) for an application or application set: - -```bash -dspmctl set-revision -``` - -**Example:** - -```bash -dspmctl set-revision netwrix 1.0.6 -``` - -### sync - -Manually trigger a sync for a specific application: - -```bash -dspmctl sync -``` - -**Example:** - -```bash -dspmctl sync netwrix.core-api -``` - -### set-helm-param - -Set one or more Helm parameter overrides for an application: - -```bash -dspmctl set-helm-param -dspmctl set-helm-param = [= ...] -``` - -**Examples:** - -```bash -# Set a single parameter -dspmctl set-helm-param netwrix.core-api image.tag v1.2.3 - -# Set multiple parameters -dspmctl set-helm-param netwrix.core-api image.tag=v1.2.3 replicaCount=2 -``` - -### version - -Display the DSPMctl version: - -```bash -dspmctl version -``` - -### help - -Display usage information: - -```bash -dspmctl --help -``` - -## Common Workflows - -### Upgrading to a New Version - -To update all applications to a new target revision: - -```bash -# Set the new version -dspmctl set-revision netwrix 1.0.7 - -# Verify applications are syncing -dspmctl auto-status - -# Force sync if needed -dspmctl sync netwrix.infra -dspmctl sync netwrix.core-api -``` - -See [Upgrading Access Analyzer](/docs/accessanalyzer/1_0/install/upgrade) for the full upgrade procedure. - -### Scaling an Application - -```bash -dspmctl set-helm-param netwrix.core-api replicaCount 3 -``` - -### Checking Deployment Health - -```bash -# Check auto-sync status -dspmctl auto-status - -# Also verify with kubectl -kubectl get apps -n argocd -kubectl get pods -n access-analyzer -``` diff --git a/docs/accessanalyzer/1.0/overview/install/environmentvariables.md b/docs/accessanalyzer/1.0/overview/install/environmentvariables.md deleted file mode 100644 index 5b2cbb6d90..0000000000 --- a/docs/accessanalyzer/1.0/overview/install/environmentvariables.md +++ /dev/null @@ -1,92 +0,0 @@ ---- -title: "Environment Variables" -description: "CLI flags and environment variable reference for the Access Analyzer installer" -sidebar_position: 30 ---- - -# Environment Variables - -The Access Analyzer installer can be configured using command-line flags or environment variables. Environment variables are useful for scripted or automated installations. - -## CLI Flags - -``` -install.sh --license-key [options] - -Options: - --license-key Netwrix license key (required) - --target-revision Application version to deploy (default: 1.*) - --size Resource size multiplier, 1–10 (default: 1) - --accept-warnings Accept preflight warnings and continue - --dry-run Run preflight checks only, without installing - --help Display usage information -``` - -## Mandatory Variables - -| Variable | CLI Flag | Description | -| --- | --- | --- | -| `LICENSE_KEY` | `--license-key` | Netwrix license key for OCI registry authentication. Required for installation. | - -## Optional Configuration Variables - -| Variable | CLI Flag | Default | Description | -| --- | --- | --- | --- | -| `DSPM_TARGET_REVISION` | `--target-revision` | `1.*` | Target version for DSPM applications | -| `SIZE` | `--size` | `1` | Resource size multiplier (1–10). Scales memory thresholds. | -| `ACCEPT_WARNINGS` | `--accept-warnings` | `false` | Set to `true` to skip preflight warning prompts | - -## Proxy Variables - -| Variable | Description | Example | -| --- | --- | --- | -| `HTTP_PROXY` | HTTP proxy server URL | `http://proxy.example.com:8080` | -| `HTTPS_PROXY` | HTTPS proxy server URL | `http://proxy.example.com:8080` | -| `NO_PROXY` | Comma-separated list of hosts to bypass proxy | `localhost,127.0.0.1,10.0.0.0/8` | - -## Advanced Variables - -These variables are intended for specialized deployments and troubleshooting. They are not required for standard installations. - -| Variable | Default | Description | -| --- | --- | --- | -| `SKIP_AV_CHECK` | `false` | Skip antivirus detection during preflight | -| `FORCE_CA_MOUNT` | `false` | Force CA certificate bundle mounting to ArgoCD components | -| `USE_LOCAL_CHARTS` | `false` | Use local Helm charts instead of OCI registry | -| `USE_MIRRORED_IMAGES` | `true` | Use mirrored container images | -| `DISABLE_DEX` | `true` | Disable the Dex identity provider in ArgoCD | -| `DISABLE_NOTIFICATIONS` | `true` | Disable ArgoCD notifications | -| `DSPM_INSTALL_DEBUG` | Not set | Enable debug logging for the installer | - -## Examples - -**Basic installation:** - -```bash -export LICENSE_KEY='' -curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash - -``` - -**Installation with a specific version:** - -```bash -export LICENSE_KEY='' -curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- --target-revision "1.0.6" -``` - -**Scaled deployment (2x resources):** - -```bash -export LICENSE_KEY='' -curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- --size 2 -``` - -**Installation behind a proxy:** - -```bash -export LICENSE_KEY='' -export HTTP_PROXY="http://proxy.example.com:8080" -export HTTPS_PROXY="http://proxy.example.com:8080" -export NO_PROXY="localhost,127.0.0.1" -curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash - -``` diff --git a/docs/accessanalyzer/1.0/overview/install/network.md b/docs/accessanalyzer/1.0/overview/install/network.md deleted file mode 100644 index 8e188d3da6..0000000000 --- a/docs/accessanalyzer/1.0/overview/install/network.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: "Network Configuration" -description: "Network requirements, outbound endpoints, and firewall rules for Access Analyzer" -sidebar_position: 20 ---- - -# Network Configuration - -Access Analyzer requires outbound HTTPS connectivity during installation to download Kubernetes components, container images, and application packages. This page lists the required endpoints and provides firewall configuration examples. - -## Required Outbound Endpoints - -The following endpoints must be reachable over HTTPS (port 443) from the Access Analyzer VM: - -| Endpoint | Purpose | -| --- | --- | -| `get.k3s.io` | K3s installer download | -| `raw.githubusercontent.com` | ArgoCD manifests (bootstrap only) | -| `oci.pkg.keygen.sh` | Netwrix OCI registry — Helm charts and application images | -| `docker.io` / `docker.com` | Container base images (PostgreSQL, ClickHouse, Redis) | - -:::note -All application packages are distributed through the Netwrix OCI registry at `oci.pkg.keygen.sh`. Access is authenticated with your license key. No external Git repository access is required. -::: - -## Firewall Rules - -### Azure VMs (Network Security Group) - -```bash -az network nsg rule create \ - --resource-group \ - --nsg-name \ - --name AllowHTTPSOutbound \ - --protocol Tcp \ - --priority 1010 \ - --destination-port-range 443 \ - --direction Outbound \ - --access Allow -``` - -### AWS EC2 (Security Groups) - -```bash -aws ec2 authorize-security-group-egress \ - --group-id \ - --protocol tcp \ - --port 443 \ - --cidr 0.0.0.0/0 -``` - -### On-Premises / Bare Metal - -Using `ufw` (Ubuntu Firewall): - -```bash -sudo ufw allow out 443/tcp -``` - -Using `iptables`: - -```bash -sudo iptables -A OUTPUT -p tcp --dport 443 -j ACCEPT -``` - -## Proxy Configuration - -If your environment routes outbound traffic through a proxy server, set the following environment variables before running the installer: - -```bash -export HTTP_PROXY="http://:" -export HTTPS_PROXY="http://:" -export NO_PROXY="localhost,127.0.0.1,10.0.0.0/8" -``` - -See [Environment Variables](/docs/accessanalyzer/1_0/install/environmentvariables) for the full list of proxy-related variables. - -## Verifying Connectivity - -Test outbound access to the required endpoints before installation: - -```bash -# Test K3s installer access -curl -I https://get.k3s.io - -# Test Netwrix registry access -curl -I https://oci.pkg.keygen.sh:443 -``` - -## Common Network Issues - -| Issue | Symptom | Solution | -| --- | --- | --- | -| Applications not syncing | `connection refused` to Keygen | Verify outbound HTTPS (443) to `oci.pkg.keygen.sh` | -| K3s installation fails | Download errors | Check connectivity to `get.k3s.io` | -| Container image pull failures | `ImagePullBackOff` pod status | Verify access to `oci.pkg.keygen.sh` and license key validity | diff --git a/docs/accessanalyzer/1.0/overview/install/overview.md b/docs/accessanalyzer/1.0/overview/install/overview.md deleted file mode 100644 index af5712a7a3..0000000000 --- a/docs/accessanalyzer/1.0/overview/install/overview.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: "Installation" -description: "Installation and deployment overview for Netwrix Access Analyzer" -sidebar_position: 1 ---- - -# Installation - -Netwrix Access Analyzer is deployed as a self-contained Kubernetes cluster on a single Linux virtual machine. The automated installer provisions all required infrastructure components — including K3s, ArgoCD, databases, and application services — with a single command. - -## Installation Paths - -Choose the installation path that best fits your needs: - -| Path | Description | Audience | -| --- | --- | --- | -| [Quick Install](/docs/accessanalyzer/1_0/install/quickinstall) | Single-page guide to get Access Analyzer running fast | Experienced Linux admins | -| [Step-by-Step Install](/docs/accessanalyzer/1_0/install/stepbystep) | Detailed walkthrough with explanations for each phase | First-time installers | - -## Before You Begin - -Review the following requirements before starting installation: - -- [Hardware and System Requirements](/docs/accessanalyzer/1_0/install/requirements) — CPU, memory, disk, OS, and virtualization -- [Network Configuration](/docs/accessanalyzer/1_0/install/network) — Outbound endpoints and firewall rules -- [Preflight Checks](/docs/accessanalyzer/1_0/install/preflight) — Automated system validation and dry-run mode - -## What the Installer Does - -The installer automates the entire deployment in approximately 15–30 minutes: - -1. **Validates prerequisites** — Runs preflight checks for hardware, OS, and network -2. **Deploys K3s** — Installs a lightweight Kubernetes distribution (v1.33.4) with secrets-at-rest encryption -3. **Installs ArgoCD** — Sets up GitOps-based application lifecycle management (v3.2.0) -4. **Deploys applications** — Pulls Helm charts from the Netwrix OCI registry and deploys all services -5. **Verifies health** — Monitors application health until all components are operational - -## After Installation - -- [Post-Installation Validation](/docs/accessanalyzer/1_0/install/postinstall) — Verify cluster health and access the ArgoCD UI -- [SSL / TLS Configuration](/docs/accessanalyzer/1_0/install/ssl) — Certificate auto-detection and custom CA bundles -- [DSPMctl CLI](/docs/accessanalyzer/1_0/install/dspmctl) — Manage applications with the built-in command-line tool - -## Additional Topics - -- [Environment Variables](/docs/accessanalyzer/1_0/install/environmentvariables) — CLI flags and environment variable reference -- [Upgrading Access Analyzer](/docs/accessanalyzer/1_0/install/upgrade) — Update to a new version -- [Uninstalling Access Analyzer](/docs/accessanalyzer/1_0/install/uninstall) — Remove the installation -- [Security Best Practices](/docs/accessanalyzer/1_0/install/security) — Harden your deployment diff --git a/docs/accessanalyzer/1.0/overview/install/preflight.md b/docs/accessanalyzer/1.0/overview/install/preflight.md deleted file mode 100644 index 6ac77af940..0000000000 --- a/docs/accessanalyzer/1.0/overview/install/preflight.md +++ /dev/null @@ -1,111 +0,0 @@ ---- -title: "Preflight Checks" -description: "System validation checks performed before installation" -sidebar_position: 25 ---- - -# Preflight Checks - -The Access Analyzer installer performs comprehensive system validation before any installation steps begin. Preflight checks verify hardware resources, kernel capabilities, and system access to prevent partial installation failures. - -## Dry-Run Mode - -Run preflight checks without installing anything using the `--dry-run` flag: - -```bash -export LICENSE_KEY='' -curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- --dry-run -``` - -Dry-run mode performs all validation checks and writes results to `/var/log/dspm-preflight.json`, then exits without modifying the system. - -## Phase 1: System Resource Validation - -| Check | Minimum | Recommended | Failure Behavior | -| --- | --- | --- | --- | -| **Total memory** | 8 GB | 16 GB | FAIL — installation blocked | -| **Available memory** | 4 GB (during install) | — | FAIL — installation blocked | -| **CPU cores** | 2 vCPUs | 4 vCPUs | FAIL — installation blocked | -| **Disk space (`/`, `/var`, `/var/lib`)** | 20 GB free | 50 GB free | FAIL — installation blocked | -| **Disk space (`/var/log`)** | 5 GB free | — | FAIL — installation blocked | -| **Disk space (`/etc`)** | 1 GB free | — | FAIL — installation blocked | -| **Write access** | `/var`, `/tmp`, `/etc` | — | FAIL — installation blocked | -| **Swap** | None required | 2–4 GB if RAM < 16 GB | WARN — continues with warning | -| **Dynamic memory** | N/A | Static allocation | WARN — continues with warning | - -## Phase 2: Kernel and System Access - -| Check | Requirement | Failure Behavior | -| --- | --- | --- | -| **System directories** | Write access to `/var` and `/etc` | FAIL — installation blocked | -| **Kernel modules** | `/proc/modules` readable | FAIL — installation blocked | -| **Control groups** | cgroups v1 or v2 with memory and CPU controllers | FAIL — installation blocked | -| **Overlay filesystem** | `overlay` kernel module loaded or available | FAIL — installation blocked | -| **Linux namespaces** | NET, PID, IPC, UTS, MNT, USER | FAIL — installation blocked | - -## Antivirus Detection - -The installer scans for active antivirus agents that may interfere with Kubernetes container operations: - -- Microsoft Defender for Endpoint (mdatp) -- CrowdStrike Falcon -- ClamAV -- Sophos -- Carbon Black -- Trend Micro - -If an antivirus agent is detected, the installer issues a warning. To skip this check, set the `SKIP_AV_CHECK` environment variable: - -```bash -export SKIP_AV_CHECK=true -``` - -## Preflight Result Log - -All preflight results are written to `/var/log/dspm-preflight.json` in structured JSON format: - -```json -{ - "timestamp": "2026-01-15T10:30:00Z", - "overall_status": "PASS", - "thresholds": { - "min_ram_gb": 8, - "min_cpu_cores": 2, - "min_disk_gb": 20 - }, - "checks": [ - { - "status": "PASS", - "component": "Memory", - "message": "Total memory sufficient for DSPM installation", - "current_value": "15.56 GB", - "threshold": "8 GB minimum" - } - ] -} -``` - -## Handling Warnings - -When preflight checks produce warnings (but no failures), the installer prompts for confirmation before proceeding. To automatically accept warnings — for example, in automated or scripted deployments — use one of the following: - -```bash -# CLI flag -curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- --accept-warnings - -# Environment variable -export ACCEPT_WARNINGS=true -``` - -## Exit Codes - -The installer uses specific exit codes to indicate failure categories: - -| Exit Code | Meaning | -| --- | --- | -| `0` | Success | -| `10` | License validation error | -| `50` | K3s installation error | -| `60` | ArgoCD installation error | -| `70` | Application deployment timeout | -| `80` | Preflight check failure | diff --git a/docs/accessanalyzer/1.0/overview/install/ssl.md b/docs/accessanalyzer/1.0/overview/install/ssl.md deleted file mode 100644 index cebd210517..0000000000 --- a/docs/accessanalyzer/1.0/overview/install/ssl.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: "SSL / TLS Configuration" -description: "Certificate auto-detection and custom CA bundle configuration for Access Analyzer" -sidebar_position: 60 ---- - -# SSL / TLS Configuration - -Access Analyzer uses HTTPS for all client-facing traffic, served through Traefik as the ingress controller. By default, a self-signed TLS certificate is generated during installation. This page covers certificate handling and custom CA bundle configuration. - -## Default Behavior - -After installation, Access Analyzer is accessible at `https://`. The default self-signed certificate causes browsers to display a security warning on first access. - -## Certificate Auto-Detection - -During installation, the installer scans for existing CA certificate bundles on the system. If a bundle is found, it is automatically mounted into ArgoCD components to enable TLS verification for outbound connections to the OCI registry and other external services. - -The installer searches the following paths: - -| Path | Description | -| --- | --- | -| `/etc/ssl/certs/ca-certificates.crt` | Debian/Ubuntu CA bundle | -| `/etc/pki/tls/certs/ca-bundle.crt` | RHEL/CentOS CA bundle | -| `/etc/ssl/ca-bundle.pem` | SUSE CA bundle | -| `/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem` | RHEL trust store | -| `/etc/ssl/cert.pem` | Alpine/macOS CA bundle | -| `/usr/local/share/ca-certificates/` | Custom CA directory | - -## Forcing CA Bundle Mounting - -If the installer does not detect your CA bundle automatically, or if you are using a custom internal CA, force CA bundle mounting with the `FORCE_CA_MOUNT` environment variable: - -```bash -export FORCE_CA_MOUNT=true -export LICENSE_KEY='' -curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash - -``` - -## Adding Custom CA Certificates - -To add a custom CA certificate to the system trust store before installation: - -```bash -# Copy your CA certificate to the system trust directory -sudo cp your-ca-cert.crt /usr/local/share/ca-certificates/ - -# Update the system CA bundle -sudo update-ca-certificates -``` - -Run the installer after updating the trust store. The installer will automatically detect and mount the updated bundle. - -## TLS for Internal Services - -All internal service-to-service communication within the Kubernetes cluster uses the cluster's internal networking. Traefik handles TLS termination at the ingress layer and routes traffic to backend services. diff --git a/docs/accessanalyzer/1.0/overview/install/stepbystep.md b/docs/accessanalyzer/1.0/overview/install/stepbystep.md deleted file mode 100644 index bd418170a7..0000000000 --- a/docs/accessanalyzer/1.0/overview/install/stepbystep.md +++ /dev/null @@ -1,150 +0,0 @@ ---- -title: "Step-by-Step Installation" -description: "Detailed walkthrough of the Access Analyzer installation process" -sidebar_position: 35 ---- - -# Step-by-Step Installation - -This guide provides a detailed walkthrough of the Netwrix Access Analyzer installation process with explanations for each phase. For a condensed version, see the [Quick Install](/docs/accessanalyzer/1_0/install/quickinstall) guide. - -## Pre-Installation Checklist - -Complete the following before starting the installer: - -| Step | Action | Reference | -| --- | --- | --- | -| 1 | Provision a Linux VM meeting hardware requirements | [Hardware and System Requirements](/docs/accessanalyzer/1_0/install/requirements) | -| 2 | Configure static memory allocation on the hypervisor | [Virtualization Configuration](/docs/accessanalyzer/1_0/install/requirements#virtualization-and-hypervisor-configuration) | -| 3 | Verify outbound HTTPS connectivity to required endpoints | [Network Configuration](/docs/accessanalyzer/1_0/install/network) | -| 4 | Obtain your Netwrix license key | Contact Netwrix Sales or Support | -| 5 | Update the operating system | See step 1 below | - -## Step 1: Update the Operating System - -Ensure all system packages are current: - -```bash -sudo apt update && sudo apt upgrade -y -``` - -Reboot if kernel updates were applied: - -```bash -sudo reboot -``` - -## Step 2: Validate System Readiness (Optional) - -Run the installer in dry-run mode to verify that the system meets all requirements without making changes: - -```bash -export LICENSE_KEY='' -curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- --dry-run -``` - -Review the results in `/var/log/dspm-preflight.json`. Address any `FAIL` items before proceeding. See [Preflight Checks](/docs/accessanalyzer/1_0/install/preflight) for details on each check. - -## Step 3: Set the License Key - -Export your Netwrix license key as an environment variable: - -```bash -export LICENSE_KEY='' -``` - -:::warning -Do not store the license key in scripts or configuration files that are committed to version control. Clear your shell history after installation — see [Security Best Practices](/docs/accessanalyzer/1_0/install/security). -::: - -## Step 4: Run the Installer - -Download and execute the installer: - -```bash -curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash - -``` - -The installer executes the following phases automatically: - -### Phase 1 — Preflight Checks - -The installer validates system resources (memory, CPU, disk), kernel features (cgroups, overlay FS, namespaces), and system access. If any critical check fails, the installer exits with code `80`. If warnings are present, you are prompted to continue or abort. - -### Phase 2 — K3s Installation - -K3s (v1.33.4+k3s1) is deployed as a lightweight Kubernetes distribution. The installer configures: - -- Kubeconfig permissions (`644`) -- Secrets-at-rest encryption -- K3s service name `dspm` - -### Phase 3 — ArgoCD Installation - -ArgoCD (v3.2.0) is deployed using Kustomize-based manifests with dynamic patches. ArgoCD provides GitOps-based application lifecycle management for all Access Analyzer components. - -### Phase 4 — DSPMctl Wrapper - -The `dspmctl` command-line tool is installed to `/usr/local/bin/dspmctl`. This tool provides convenient commands for managing ArgoCD applications. See [DSPMctl CLI](/docs/accessanalyzer/1_0/install/dspmctl). - -### Phase 5 — Application Deployment - -Applications are deployed from the Netwrix OCI registry (`oci://oci.pkg.keygen.sh/netwrix/dspm-apps-helm`). ArgoCD pulls Helm charts and deploys all services into the `access-analyzer` namespace. - -### Phase 6 — Health Verification - -The installer monitors application health with a 30-minute timeout, checking every 2 seconds. Once all applications report healthy status, the installer prints a success summary. - -## Step 5: Verify the Installation - -After the installer completes successfully, verify the cluster state: - -```bash -# Check all pods across all namespaces -kubectl get pods -A - -# Check ArgoCD application sync status -kubectl get apps -n argocd - -# Check node resource usage -kubectl top nodes -``` - -All pods should be in `Running` or `Completed` status. All ArgoCD applications should show `Synced` and `Healthy`. - -## Step 6: Access the Application - -Open a browser and navigate to: - -``` -https:// -``` - -:::note -Access Analyzer uses a self-signed TLS certificate by default. Your browser will display a security warning — accept it to proceed. See [SSL / TLS Configuration](/docs/accessanalyzer/1_0/install/ssl) for custom certificate setup. -::: - -## Step 7: Create the First Admin Account - -1. On the login page, click **Create Account** -2. Enter your full name, email address, and a password -3. Click **Create Account** - -The first account created is automatically assigned the **Administrator** role with full access to all features. - -## Step 8: Sign In - -1. Enter your email address and password -2. Click **Sign In** - -You are now ready to begin configuring Access Analyzer. See [Getting Started](/docs/accessanalyzer/1_0/gettingstarted/overview) for your next steps. - -## Installation Log - -The installer writes a detailed log to `/var/log/dspm-installer.log`. If the installation fails, review this file for diagnostic information: - -```bash -cat /var/log/dspm-installer.log -``` - -For additional troubleshooting guidance, see [Troubleshooting](/docs/accessanalyzer/1_0/troubleshooting/overview). diff --git a/docs/accessanalyzer/1.0/overview/install/upgrade.md b/docs/accessanalyzer/1.0/overview/install/upgrade.md deleted file mode 100644 index 868b81dc33..0000000000 --- a/docs/accessanalyzer/1.0/overview/install/upgrade.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: "Upgrading Access Analyzer" -description: "Update Access Analyzer to a new version using DSPMctl" -sidebar_position: 70 ---- - -# Upgrading Access Analyzer - -Access Analyzer uses ArgoCD for GitOps-based application management. Upgrades are performed by updating the target revision, which triggers ArgoCD to pull and deploy the new version from the Netwrix OCI registry. - -## Upgrade Procedure - -### Step 1: Check Current Version - -```bash -dspmctl auto-status -``` - -Note the current target revision displayed for each application. - -### Step 2: Set the New Target Revision - -Update the target revision to the desired version: - -```bash -dspmctl set-revision netwrix -``` - -**Example:** - -```bash -dspmctl set-revision netwrix 1.0.7 -``` - -### Step 3: Monitor the Upgrade - -If auto-sync is enabled, ArgoCD automatically detects the revision change and begins deploying the new version. Monitor the status: - -```bash -# Watch ArgoCD application sync status -kubectl get apps -n argocd -w - -# Check DSPMctl status -dspmctl auto-status -``` - -If auto-sync is not enabled, manually trigger the sync: - -```bash -dspmctl sync netwrix.infra -dspmctl sync netwrix.core-api -``` - -### Step 4: Verify the Upgrade - -Confirm all applications are synced and healthy: - -```bash -kubectl get apps -n argocd -kubectl get pods -n access-analyzer -``` - -All applications should show `Synced` and `Healthy` status. All pods should be `Running` or `Completed`. - -## Rollback - -To revert to a previous version, set the target revision back: - -```bash -dspmctl set-revision netwrix -``` - -ArgoCD will redeploy the previous version. - -:::warning -Test upgrades in a non-production environment before applying to production systems. -::: diff --git a/docs/accessanalyzer/1.0/overview/overview.md b/docs/accessanalyzer/1.0/overview/overview.md deleted file mode 100644 index 6dc74163a7..0000000000 --- a/docs/accessanalyzer/1.0/overview/overview.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: "Intro to the Product" -description: "Introduction to Netwrix Access Analyzer and its capabilities" -sidebar_position: 10 ---- - -# Intro to the Product - -Netwrix Access Analyzer is an on-premises Data Security Posture Management (DSPM) platform that discovers, classifies, and secures sensitive data across your organization's file systems. Deployed on your own infrastructure, it provides visibility into who has access to what data, identifies overly permissive access, and detects sensitive data exposure — all without sending data to the cloud. - -## Core Capabilities - -- **Data Source Discovery** — Connect to file shares (CIFS/SMB) and other on-premises data repositories to inventory content and access permissions -- **Identity and Access Analysis** — Synchronize with Active Directory, Entra ID, and local groups to map identities, group memberships, and effective permissions -- **Sensitive Data Detection** — Scan files for PII, credentials, PHI, and financial records using built-in patterns and custom regex rules, with compliance mappings to GDPR, CCPA, HIPAA, PCI DSS, GLBA, and CMMC -- **Dashboards and Reporting** — View findings through embedded Metabase dashboards for data security posture, Active Directory insights, and sensitive data exposure -- **Audit Trail** — Maintain a full audit log of user actions and system events - -## How It Works - -1. **Configure data sources** — Add file shares and identity providers as data sources, each with an associated service account for authentication -2. **Run scans** — Create access scans to enumerate permissions and sensitive data scans to classify content -3. **Review findings** — Analyze results through dashboards, reports, and the scan execution history -4. **Take action** — Identify and remediate overly permissive access, exposed sensitive data, and policy violations - -## Deployment Model - -Access Analyzer is deployed on-premises as a self-contained Kubernetes cluster on a single Linux VM within your own network. A one-command installer provisions all required infrastructure — including K3s, ArgoCD, databases, and application services. No cloud connectivity is required. Updates are managed through ArgoCD GitOps. - -For installation instructions, see [Installation](/docs/accessanalyzer/1_0/overview/install/overview). - -## What's Next - -- [Key Concepts](/docs/accessanalyzer/1_0/overview/keyconcepts) — Learn the terminology used throughout Access Analyzer -- [Requirements](/docs/accessanalyzer/1_0/overview/requirements/overview) — Review system and connector requirements -- [Installation](/docs/accessanalyzer/1_0/overview/install/overview) — Install Access Analyzer on your infrastructure diff --git a/docs/accessanalyzer/1.0/overview/requirements/_category_.json b/docs/accessanalyzer/1.0/overview/requirements/_category_.json deleted file mode 100644 index 2047289ac1..0000000000 --- a/docs/accessanalyzer/1.0/overview/requirements/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Requirements", - "position": 30, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/overview/requirements/connectors/localgroups.md b/docs/accessanalyzer/1.0/overview/requirements/connectors/localgroups.md deleted file mode 100644 index ac5efd6ad9..0000000000 --- a/docs/accessanalyzer/1.0/overview/requirements/connectors/localgroups.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: "Local Groups" -description: "PowerShell Remoting and target machine permissions" -sidebar_position: 50 ---- - -# Local Groups - -The Local Groups connector enumerates local users and group memberships on Windows machines using PowerShell Remoting (WinRM). - -## Network Requirements - -| Port | Protocol | Direction | Description | -| --- | --- | --- | --- | -| 5985 | TCP | Access Analyzer → Target Machine | WinRM over HTTP | -| 5986 | TCP | Access Analyzer → Target Machine | WinRM over HTTPS | - -## Service Account Requirements - -| Requirement | Details | -| --- | --- | -| **Account type** | Local administrator or member of Remote Management Users group | -| **Authentication** | Username and password | -| **WinRM** | PowerShell Remoting must be enabled on target machines | - -## Enabling WinRM on Target Machines - -PowerShell Remoting must be enabled on each target machine: - -```powershell -Enable-PSRemoting -Force -``` - -For domain-joined machines, this can be configured via Group Policy: - -1. Open **Group Policy Management** -2. Navigate to **Computer Configuration** > **Administrative Templates** > **Windows Components** > **Windows Remote Management (WinRM)** > **WinRM Service** -3. Enable **Allow remote server management through WinRM** - -## Credential Type - -| Field | Value | -| --- | --- | -| **Type** | Username / Password | -| **Username format** | `MACHINE\username` or `DOMAIN\username` | - -## Connector Capabilities - -| Operation | Description | -| --- | --- | -| **Test connection** | Validates WinRM connectivity and authentication | -| **Sync** | Enumerates local users, groups, and group memberships | diff --git a/docs/accessanalyzer/1.0/overview/requirements/connectors/sharepointonline.md b/docs/accessanalyzer/1.0/overview/requirements/connectors/sharepointonline.md deleted file mode 100644 index 4e06241002..0000000000 --- a/docs/accessanalyzer/1.0/overview/requirements/connectors/sharepointonline.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: "SharePoint Online" -description: "Azure App Registration, Graph API permissions, and certificate authentication" -sidebar_position: 20 ---- - -# SharePoint Online - -The SharePoint Online connector scans SharePoint sites to enumerate content and access permissions using the Microsoft Graph API with certificate-based authentication. - -## Network Requirements - -| Port | Protocol | Direction | Description | -| --- | --- | --- | --- | -| 443 | TCP | Access Analyzer → Microsoft Graph API | HTTPS | - -## Azure App Registration - -An Azure AD (Entra ID) app registration is required for SharePoint Online connectivity. - -### Required API Permissions - -| Permission | Type | Description | -| --- | --- | --- | -| `Sites.Read.All` | Application | Read items in all site collections | - -### Registration Steps - -1. Sign in to the [Azure portal](https://portal.azure.com) and navigate to **Microsoft Entra ID** > **App registrations** -2. Click **New registration** and provide a name (for example, `Netwrix Access Analyzer - SharePoint`) -3. Under **API permissions**, add the **Microsoft Graph** application permission `Sites.Read.All` -4. Grant admin consent for the permission -5. Under **Certificates & secrets**, upload a certificate (`.cer` or `.pem` public key) -6. Note the **Application (client) ID** and **Tenant ID** - -## Credential Type - -| Field | Value | -| --- | --- | -| **Type** | Certificate | -| **Client ID** | Application (client) ID from the app registration | -| **Tenant ID** | Directory (tenant) ID | -| **Certificate** | Private key file (`.pem`) corresponding to the uploaded public key | - -## Connector Capabilities - -| Operation | Description | -| --- | --- | -| **Test connection** | Validates Graph API connectivity and certificate authentication | -| **Access scan** | Enumerates SharePoint sites, document libraries, files, and permissions | -| **Get object** | Retrieves specific site or document metadata | - -## Scan Configuration Options - -| Option | Description | -| --- | --- | -| **Site filtering** | Include or exclude specific SharePoint sites | diff --git a/docs/accessanalyzer/1.0/overview/requirements/database/_category_.json b/docs/accessanalyzer/1.0/overview/requirements/database/_category_.json deleted file mode 100644 index 32e43edc04..0000000000 --- a/docs/accessanalyzer/1.0/overview/requirements/database/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Database Requirements", - "position": 20, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "postgresql" - } -} diff --git a/docs/accessanalyzer/1.0/overview/requirements/database/clickhouse.md b/docs/accessanalyzer/1.0/overview/requirements/database/clickhouse.md deleted file mode 100644 index 868c10e9da..0000000000 --- a/docs/accessanalyzer/1.0/overview/requirements/database/clickhouse.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: "ClickHouse" -description: "ClickHouse version and configuration" -sidebar_position: 20 ---- - -# ClickHouse - -ClickHouse is a columnar analytics database used by Access Analyzer for scan results, reporting data, and observability (OpenTelemetry traces and logs). - -## Version - -| Component | Value | -| --- | --- | -| **ClickHouse version** | 25.8.13 | -| **Namespace** | `access-analyzer` | -| **HTTP interface port** | 8123 | -| **Native protocol port** | 9000 | - -## Provisioning - -ClickHouse is **automatically provisioned** by the installer. No manual setup is required. - -Database passwords are auto-generated and stored as Kubernetes secrets. - -## Data Stored - -- Scan results and analytics data -- OpenTelemetry traces and logs (via the `access_analyzer_logs` database) -- Reporting and dashboard data queried by Metabase diff --git a/docs/accessanalyzer/1.0/overview/requirements/database/postgresql.md b/docs/accessanalyzer/1.0/overview/requirements/database/postgresql.md deleted file mode 100644 index 4e5f9dba79..0000000000 --- a/docs/accessanalyzer/1.0/overview/requirements/database/postgresql.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: "PostgreSQL" -description: "PostgreSQL version and configuration" -sidebar_position: 10 ---- - -# PostgreSQL - -PostgreSQL serves as the primary relational database for Access Analyzer, storing configuration, user accounts, scan metadata, connector state, and application data. - -## Version - -| Component | Value | -| --- | --- | -| **PostgreSQL version** | 14.18 | -| **Namespace** | `access-analyzer` | - -## Provisioning - -PostgreSQL is **automatically provisioned** by the installer. No manual database setup, schema creation, or user configuration is required. - -The installer creates the following database users during deployment: - -| User | Purpose | -| --- | --- | -| `postgres` | Superuser for administrative tasks | -| `connector_readonly` | Read-only access for connector queries | -| `connector_execution_update` | Write access for connector execution state | -| `connector_state_readwrite` | Read/write access for connector state management | - -All database passwords are auto-generated by the `dspm-utility` secret initialization process and stored as Kubernetes secrets. - -## Data Stored - -- User accounts and authentication -- Source and scan configuration -- Service accounts (encrypted credentials) -- Connector state and execution metadata -- Application settings and feature flags -- Audit log entries diff --git a/docs/accessanalyzer/1.0/overview/requirements/database/redis.md b/docs/accessanalyzer/1.0/overview/requirements/database/redis.md deleted file mode 100644 index 9cc26151cb..0000000000 --- a/docs/accessanalyzer/1.0/overview/requirements/database/redis.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: "Redis" -description: "Redis version and configuration" -sidebar_position: 30 ---- - -# Redis - -Redis provides in-memory caching, session storage, and job queue management for Access Analyzer. - -## Version - -| Component | Value | -| --- | --- | -| **Redis version** | 8.4.0 | -| **Namespace** | `access-analyzer` | -| **Port** | 6379 | - -## Provisioning - -Redis is **automatically provisioned** by the installer. No manual setup is required. - -## Data Stored - -| Function | Description | -| --- | --- | -| **User sessions** | Session data for authenticated users (with IP validation and configurable TTL) | -| **Sidekiq job queues** | Background job processing for scans, syncs, mailers, and system tasks | -| **Application cache** | Frequently accessed data for reduced database load | - -## Job Queues - -Redis backs the Sidekiq job processing system, which uses the following queues: - -| Queue | Purpose | -| --- | --- | -| `critical` | High-priority system operations | -| `scans` | Scan execution jobs | -| `syncs` | Identity synchronization jobs | -| `scheduler` | Scheduled job dispatch | -| `default` | General-purpose jobs | -| `mailers` | Email notification delivery | -| `low` | Low-priority background tasks | diff --git a/docs/accessanalyzer/1.0/overview/requirements/overview.md b/docs/accessanalyzer/1.0/overview/requirements/overview.md deleted file mode 100644 index 84fa865f34..0000000000 --- a/docs/accessanalyzer/1.0/overview/requirements/overview.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: "Requirements" -description: "System, database, and connector requirements for Access Analyzer" -sidebar_position: 1 ---- - -# Requirements - -This section covers all prerequisites for deploying and operating Netwrix Access Analyzer. - -## System Requirements - -The Access Analyzer VM must meet minimum hardware, operating system, and kernel requirements. The installer validates these automatically during [preflight checks](/docs/accessanalyzer/1_0/install/preflight). - -- [Kubernetes and Operating System](/docs/accessanalyzer/1_0/requirements/system/kubernetes) — OS version, kernel, and K3s details -- [Hardware and Resource Allocation](/docs/accessanalyzer/1_0/requirements/system/hardware) — CPU, memory, disk, and virtualization -- [Network and Port Requirements](/docs/accessanalyzer/1_0/requirements/system/network) — Outbound endpoints, internal ports, and firewall rules - -## Database Requirements - -All databases are automatically provisioned by the installer. No manual database setup is required. - -- [PostgreSQL](/docs/accessanalyzer/1_0/requirements/database/postgresql) — Primary relational database -- [ClickHouse](/docs/accessanalyzer/1_0/requirements/database/clickhouse) — Analytics and observability database -- [Redis](/docs/accessanalyzer/1_0/requirements/database/redis) — Session cache and job queues - -## Connector Requirements - -Each connector type has specific requirements for authentication, network access, and permissions on the target system. - -- [CIFS / SMB File Share](/docs/accessanalyzer/1_0/requirements/connectors/cifs) — SMB file share scanning -- [SharePoint Online](/docs/accessanalyzer/1_0/requirements/connectors/sharepointonline) — SharePoint site scanning -- [Active Directory](/docs/accessanalyzer/1_0/requirements/connectors/activedirectory) — AD identity synchronization -- [Entra ID](/docs/accessanalyzer/1_0/requirements/connectors/entraid) — Entra ID connection testing -- [Local Groups](/docs/accessanalyzer/1_0/requirements/connectors/localgroups) — Local group enumeration diff --git a/docs/accessanalyzer/1.0/overview/requirements/system/hardware.md b/docs/accessanalyzer/1.0/overview/requirements/system/hardware.md deleted file mode 100644 index 7787c810de..0000000000 --- a/docs/accessanalyzer/1.0/overview/requirements/system/hardware.md +++ /dev/null @@ -1,84 +0,0 @@ ---- -title: "Hardware and Resource Allocation" -description: "CPU, memory, storage, and virtualization requirements" -sidebar_position: 20 ---- - -# Hardware and Resource Allocation - -Access Analyzer is deployed on a single Linux virtual machine. This page details the hardware requirements and virtualization configuration. - -## Deployment Sizing - -| Size | CPU | Memory | Disk | Use Case | -| --- | --- | --- | --- | --- | -| **Small** | 2 vCPUs (4 recommended) | 8 GB (16 GB recommended) | 20 GB free (50 GB recommended) | Evaluation and small environments | -| **Medium** | 8 vCPUs | 32 GB | 100 GB SSD | Mid-size environments | -| **Large** | 16 vCPUs | 64 GB | 500 GB SSD | Large enterprise environments | - -All sizes require SSD or NVMe storage for optimal database performance. - -## Disk Space by Directory - -| Path | Minimum Free Space | Purpose | -| --- | --- | --- | -| `/` | 20 GB | Root filesystem | -| `/var` | 20 GB | K3s data, containers, logs | -| `/var/lib` | 20 GB | K3s data directory | -| `/var/log` | 5 GB | System and application logs | -| `/etc` | 1 GB | Configuration files | - -## Virtualization Requirements - -When running on a hypervisor, the following must be supported: - -| Requirement | Details | -| --- | --- | -| **Linux namespaces** | NET, PID, IPC, UTS, MNT, USER | -| **Control groups** | cgroups v1 or v2 with memory and CPU controllers | -| **Overlay filesystem** | Kernel module for container layers | -| **iptables** | Kubernetes networking | - -## Hypervisor Configuration - -Configure **static memory allocation** for the Access Analyzer VM. Dynamic or ballooned memory can cause resource underestimation and out-of-memory conditions. - -### VMware vSphere / ESXi - -Disable memory ballooning: - -``` -sched.mem.pshare.enable = "FALSE" -mem.balloon.enable = "FALSE" -``` - -Set these in **VM Settings** > **VM Options** > **Advanced** > **Edit Configuration**. - -### Microsoft Hyper-V - -Use static memory: - -```powershell -Set-VMMemory -VMName "" -DynamicMemoryEnabled $false -StartupBytes 16GB -``` - -### KVM / QEMU - -Use hugepages: - -```xml - - - -``` - -## Swap - -| System Memory | Recommendation | -| --- | --- | -| 16 GB or more | Swap is optional | -| Less than 16 GB | 2–4 GB swap recommended to prevent OOM during container pulls | - -## Resource Scaling - -The installer supports a `--size` flag (1–10) that scales memory thresholds by the specified multiplier. For example, `--size 2` doubles the minimum and recommended memory requirements. See [Environment Variables](/docs/accessanalyzer/1_0/install/environmentvariables). diff --git a/docs/accessanalyzer/1.0/reports-overview/_category_.json b/docs/accessanalyzer/1.0/reports-overview/_category_.json new file mode 100644 index 0000000000..6385d557da --- /dev/null +++ b/docs/accessanalyzer/1.0/reports-overview/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Reports Overview", + "position": 60, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/reports-overview/access.md b/docs/accessanalyzer/1.0/reports-overview/access.md new file mode 100644 index 0000000000..9a04e9e2bb --- /dev/null +++ b/docs/accessanalyzer/1.0/reports-overview/access.md @@ -0,0 +1,9 @@ +--- +title: "Access" +description: "Access reports overview" +sidebar_position: 20 +--- + +# Access + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/reports-overview/activity.md b/docs/accessanalyzer/1.0/reports-overview/activity.md new file mode 100644 index 0000000000..81f8f5a9ca --- /dev/null +++ b/docs/accessanalyzer/1.0/reports-overview/activity.md @@ -0,0 +1,9 @@ +--- +title: "Activity" +description: "Activity reports overview" +sidebar_position: 40 +--- + +# Activity + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/reports-overview/content.md b/docs/accessanalyzer/1.0/reports-overview/content.md new file mode 100644 index 0000000000..855c66175a --- /dev/null +++ b/docs/accessanalyzer/1.0/reports-overview/content.md @@ -0,0 +1,9 @@ +--- +title: "Content" +description: "Content reports overview" +sidebar_position: 30 +--- + +# Content + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/reports-overview/how-to-analyze-the-data.md b/docs/accessanalyzer/1.0/reports-overview/how-to-analyze-the-data.md new file mode 100644 index 0000000000..704180131f --- /dev/null +++ b/docs/accessanalyzer/1.0/reports-overview/how-to-analyze-the-data.md @@ -0,0 +1,9 @@ +--- +title: "How to Analyze the Data" +description: "Learn how to analyze data presented in reports" +sidebar_position: 10 +--- + +# How to Analyze the Data + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/reports-overview/my-reports.md b/docs/accessanalyzer/1.0/reports-overview/my-reports.md new file mode 100644 index 0000000000..26f3a69cab --- /dev/null +++ b/docs/accessanalyzer/1.0/reports-overview/my-reports.md @@ -0,0 +1,9 @@ +--- +title: "My Reports" +description: "Custom saved reports" +sidebar_position: 60 +--- + +# My Reports + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/reports-overview/sensitive-data.md b/docs/accessanalyzer/1.0/reports-overview/sensitive-data.md new file mode 100644 index 0000000000..6cdd68075f --- /dev/null +++ b/docs/accessanalyzer/1.0/reports-overview/sensitive-data.md @@ -0,0 +1,9 @@ +--- +title: "Sensitive Data" +description: "Sensitive data reports overview" +sidebar_position: 50 +--- + +# Sensitive Data + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/scanners/_category_.json b/docs/accessanalyzer/1.0/scanners/_category_.json new file mode 100644 index 0000000000..06591067c1 --- /dev/null +++ b/docs/accessanalyzer/1.0/scanners/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Utilizing Scanners", + "position": 40, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/scanners/overview.md b/docs/accessanalyzer/1.0/scanners/overview.md new file mode 100644 index 0000000000..d540453a0f --- /dev/null +++ b/docs/accessanalyzer/1.0/scanners/overview.md @@ -0,0 +1,9 @@ +--- +title: "Utilizing Scanners" +description: "Overview of scanner capabilities in Access Analyzer" +sidebar_position: 10 +--- + +# Utilizing Scanners + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/overview/requirements/system/_category_.json b/docs/accessanalyzer/1.0/system/_category_.json similarity index 88% rename from docs/accessanalyzer/1.0/overview/requirements/system/_category_.json rename to docs/accessanalyzer/1.0/system/_category_.json index 950fb05a5f..684c03e579 100644 --- a/docs/accessanalyzer/1.0/overview/requirements/system/_category_.json +++ b/docs/accessanalyzer/1.0/system/_category_.json @@ -1,6 +1,6 @@ { "label": "System Requirements", - "position": 10, + "position": 12, "collapsed": true, "collapsible": true, "link": { diff --git a/docs/accessanalyzer/1.0/overview/requirements/system/kubernetes.md b/docs/accessanalyzer/1.0/system/kubernetes.md similarity index 100% rename from docs/accessanalyzer/1.0/overview/requirements/system/kubernetes.md rename to docs/accessanalyzer/1.0/system/kubernetes.md diff --git a/docs/accessanalyzer/1.0/overview/requirements/system/network.md b/docs/accessanalyzer/1.0/system/network.md similarity index 100% rename from docs/accessanalyzer/1.0/overview/requirements/system/network.md rename to docs/accessanalyzer/1.0/system/network.md diff --git a/docs/accessanalyzer/1.0/overview/install/requirements.md b/docs/accessanalyzer/1.0/system/requirements.md similarity index 100% rename from docs/accessanalyzer/1.0/overview/install/requirements.md rename to docs/accessanalyzer/1.0/system/requirements.md From ade6132401bf1d0e618985ffa1735accd5adf884 Mon Sep 17 00:00:00 2001 From: carlos-mejia_nwx Date: Tue, 31 Mar 2026 11:36:28 -0400 Subject: [PATCH 04/62] =?UTF-8?q?AA26:=20Restructure=20outline=20=E2=80=94?= =?UTF-8?q?=20File=20Servers=20subsections,=20merge=20Dashboards/Reports,?= =?UTF-8?q?=20scanner=20subsections?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - File Servers: converted to directory, moved CIFS under it, added Unity, Celerra, VNX, NetApp - Dashboards and Reports: merged Dashboards Overview + Reports Overview into single section - Removed access, content, activity, sensitive data report pages; kept My Reports - Added How to Analyze Reports subsection - Utilizing Scanners: renamed overview, added Best Practices subsection Co-Authored-By: Claude Opus 4.6 --- docs/accessanalyzer/1.0/connectors/_category_.json | 6 +----- docs/accessanalyzer/1.0/connectors/file-servers.md | 9 --------- .../1.0/connectors/file-servers/_category_.json | 6 ++++++ .../1.0/connectors/file-servers/celerra.md | 9 +++++++++ .../1.0/connectors/{ => file-servers}/cifs.md | 0 .../accessanalyzer/1.0/connectors/file-servers/netapp.md | 9 +++++++++ docs/accessanalyzer/1.0/connectors/file-servers/unity.md | 9 +++++++++ docs/accessanalyzer/1.0/connectors/file-servers/vnx.md | 9 +++++++++ .../1.0/dashboards-overview/how-to-analyze-the-data.md | 9 --------- .../_category_.json | 2 +- .../active-directory-dashboard/_category_.json | 2 +- .../active-directory-dashboard/overview.md | 9 +++++++++ .../data-security-dashboard/_category_.json | 2 +- .../data-security-dashboard/activity.md | 0 .../data-security-dashboard/overview.md | 0 .../1.0/dashboards-reports/how-to-analyze-reports.md | 9 +++++++++ .../how-to-analyze-the-data.md | 2 +- .../my-reports.md | 2 +- docs/accessanalyzer/1.0/reports-overview/_category_.json | 6 ------ docs/accessanalyzer/1.0/reports-overview/access.md | 9 --------- docs/accessanalyzer/1.0/reports-overview/activity.md | 9 --------- docs/accessanalyzer/1.0/reports-overview/content.md | 9 --------- .../1.0/reports-overview/sensitive-data.md | 9 --------- docs/accessanalyzer/1.0/scanners/best-practices.md | 9 +++++++++ docs/accessanalyzer/1.0/scanners/overview.md | 4 ++-- 25 files changed, 77 insertions(+), 72 deletions(-) delete mode 100644 docs/accessanalyzer/1.0/connectors/file-servers.md create mode 100644 docs/accessanalyzer/1.0/connectors/file-servers/_category_.json create mode 100644 docs/accessanalyzer/1.0/connectors/file-servers/celerra.md rename docs/accessanalyzer/1.0/connectors/{ => file-servers}/cifs.md (100%) create mode 100644 docs/accessanalyzer/1.0/connectors/file-servers/netapp.md create mode 100644 docs/accessanalyzer/1.0/connectors/file-servers/unity.md create mode 100644 docs/accessanalyzer/1.0/connectors/file-servers/vnx.md delete mode 100644 docs/accessanalyzer/1.0/dashboards-overview/how-to-analyze-the-data.md rename docs/accessanalyzer/1.0/{dashboards-overview => dashboards-reports}/_category_.json (63%) rename docs/accessanalyzer/1.0/{dashboards-overview => dashboards-reports}/active-directory-dashboard/_category_.json (83%) create mode 100644 docs/accessanalyzer/1.0/dashboards-reports/active-directory-dashboard/overview.md rename docs/accessanalyzer/1.0/{dashboards-overview => dashboards-reports}/data-security-dashboard/_category_.json (82%) rename docs/accessanalyzer/1.0/{dashboards-overview => dashboards-reports}/data-security-dashboard/activity.md (100%) rename docs/accessanalyzer/1.0/{dashboards-overview => dashboards-reports}/data-security-dashboard/overview.md (100%) create mode 100644 docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-reports.md rename docs/accessanalyzer/1.0/{reports-overview => dashboards-reports}/how-to-analyze-the-data.md (60%) rename docs/accessanalyzer/1.0/{reports-overview => dashboards-reports}/my-reports.md (82%) delete mode 100644 docs/accessanalyzer/1.0/reports-overview/_category_.json delete mode 100644 docs/accessanalyzer/1.0/reports-overview/access.md delete mode 100644 docs/accessanalyzer/1.0/reports-overview/activity.md delete mode 100644 docs/accessanalyzer/1.0/reports-overview/content.md delete mode 100644 docs/accessanalyzer/1.0/reports-overview/sensitive-data.md create mode 100644 docs/accessanalyzer/1.0/scanners/best-practices.md diff --git a/docs/accessanalyzer/1.0/connectors/_category_.json b/docs/accessanalyzer/1.0/connectors/_category_.json index 4ebd7ecb5d..67fabb3b53 100644 --- a/docs/accessanalyzer/1.0/connectors/_category_.json +++ b/docs/accessanalyzer/1.0/connectors/_category_.json @@ -2,9 +2,5 @@ "label": "Connector Requirements", "position": 14, "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "cifs" - } + "collapsible": true } diff --git a/docs/accessanalyzer/1.0/connectors/file-servers.md b/docs/accessanalyzer/1.0/connectors/file-servers.md deleted file mode 100644 index a70313521e..0000000000 --- a/docs/accessanalyzer/1.0/connectors/file-servers.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "File Servers" -description: "File server connector requirements for Access Analyzer" -sidebar_position: 20 ---- - -# File Servers - -*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/connectors/file-servers/_category_.json b/docs/accessanalyzer/1.0/connectors/file-servers/_category_.json new file mode 100644 index 0000000000..5923518b84 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/file-servers/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "File Servers", + "position": 20, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/connectors/file-servers/celerra.md b/docs/accessanalyzer/1.0/connectors/file-servers/celerra.md new file mode 100644 index 0000000000..e562473a05 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/file-servers/celerra.md @@ -0,0 +1,9 @@ +--- +title: "Celerra" +description: "Connector requirements for Dell Celerra file servers" +sidebar_position: 30 +--- + +# Celerra + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/connectors/cifs.md b/docs/accessanalyzer/1.0/connectors/file-servers/cifs.md similarity index 100% rename from docs/accessanalyzer/1.0/connectors/cifs.md rename to docs/accessanalyzer/1.0/connectors/file-servers/cifs.md diff --git a/docs/accessanalyzer/1.0/connectors/file-servers/netapp.md b/docs/accessanalyzer/1.0/connectors/file-servers/netapp.md new file mode 100644 index 0000000000..17eab35605 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/file-servers/netapp.md @@ -0,0 +1,9 @@ +--- +title: "NetApp" +description: "Connector requirements for NetApp file servers" +sidebar_position: 50 +--- + +# NetApp + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/connectors/file-servers/unity.md b/docs/accessanalyzer/1.0/connectors/file-servers/unity.md new file mode 100644 index 0000000000..55cc8ba73a --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/file-servers/unity.md @@ -0,0 +1,9 @@ +--- +title: "Unity" +description: "Connector requirements for Dell Unity file servers" +sidebar_position: 20 +--- + +# Unity + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/connectors/file-servers/vnx.md b/docs/accessanalyzer/1.0/connectors/file-servers/vnx.md new file mode 100644 index 0000000000..cbaba1af7a --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/file-servers/vnx.md @@ -0,0 +1,9 @@ +--- +title: "VNX" +description: "Connector requirements for Dell VNX file servers" +sidebar_position: 40 +--- + +# VNX + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/dashboards-overview/how-to-analyze-the-data.md b/docs/accessanalyzer/1.0/dashboards-overview/how-to-analyze-the-data.md deleted file mode 100644 index dfb66b947e..0000000000 --- a/docs/accessanalyzer/1.0/dashboards-overview/how-to-analyze-the-data.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "How to Analyze the Data" -description: "Learn how to analyze data presented in dashboards" -sidebar_position: 10 ---- - -# How to Analyze the Data - -*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/dashboards-overview/_category_.json b/docs/accessanalyzer/1.0/dashboards-reports/_category_.json similarity index 63% rename from docs/accessanalyzer/1.0/dashboards-overview/_category_.json rename to docs/accessanalyzer/1.0/dashboards-reports/_category_.json index 2ce5a39907..91e8e50995 100644 --- a/docs/accessanalyzer/1.0/dashboards-overview/_category_.json +++ b/docs/accessanalyzer/1.0/dashboards-reports/_category_.json @@ -1,5 +1,5 @@ { - "label": "Dashboards Overview", + "label": "Dashboards and Reports", "position": 50, "collapsed": true, "collapsible": true diff --git a/docs/accessanalyzer/1.0/dashboards-overview/active-directory-dashboard/_category_.json b/docs/accessanalyzer/1.0/dashboards-reports/active-directory-dashboard/_category_.json similarity index 83% rename from docs/accessanalyzer/1.0/dashboards-overview/active-directory-dashboard/_category_.json rename to docs/accessanalyzer/1.0/dashboards-reports/active-directory-dashboard/_category_.json index 527eda587f..1625f523d8 100644 --- a/docs/accessanalyzer/1.0/dashboards-overview/active-directory-dashboard/_category_.json +++ b/docs/accessanalyzer/1.0/dashboards-reports/active-directory-dashboard/_category_.json @@ -1,6 +1,6 @@ { "label": "Active Directory Dashboard", - "position": 30, + "position": 50, "collapsed": true, "collapsible": true } diff --git a/docs/accessanalyzer/1.0/dashboards-reports/active-directory-dashboard/overview.md b/docs/accessanalyzer/1.0/dashboards-reports/active-directory-dashboard/overview.md new file mode 100644 index 0000000000..be8af55027 --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards-reports/active-directory-dashboard/overview.md @@ -0,0 +1,9 @@ +--- +title: "Overview" +description: "Overview of the Active Directory Dashboard" +sidebar_position: 10 +--- + +# Overview + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/_category_.json b/docs/accessanalyzer/1.0/dashboards-reports/data-security-dashboard/_category_.json similarity index 82% rename from docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/_category_.json rename to docs/accessanalyzer/1.0/dashboards-reports/data-security-dashboard/_category_.json index d27cd7ee77..48567d27b0 100644 --- a/docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/_category_.json +++ b/docs/accessanalyzer/1.0/dashboards-reports/data-security-dashboard/_category_.json @@ -1,6 +1,6 @@ { "label": "Data Security Dashboard", - "position": 20, + "position": 40, "collapsed": true, "collapsible": true } diff --git a/docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/activity.md b/docs/accessanalyzer/1.0/dashboards-reports/data-security-dashboard/activity.md similarity index 100% rename from docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/activity.md rename to docs/accessanalyzer/1.0/dashboards-reports/data-security-dashboard/activity.md diff --git a/docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/overview.md b/docs/accessanalyzer/1.0/dashboards-reports/data-security-dashboard/overview.md similarity index 100% rename from docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/overview.md rename to docs/accessanalyzer/1.0/dashboards-reports/data-security-dashboard/overview.md diff --git a/docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-reports.md b/docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-reports.md new file mode 100644 index 0000000000..3070386614 --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-reports.md @@ -0,0 +1,9 @@ +--- +title: "How to Analyze Reports" +description: "Guide to analyzing reports in Access Analyzer" +sidebar_position: 20 +--- + +# How to Analyze Reports + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/reports-overview/how-to-analyze-the-data.md b/docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-the-data.md similarity index 60% rename from docs/accessanalyzer/1.0/reports-overview/how-to-analyze-the-data.md rename to docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-the-data.md index 704180131f..c6dbb29a93 100644 --- a/docs/accessanalyzer/1.0/reports-overview/how-to-analyze-the-data.md +++ b/docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-the-data.md @@ -1,6 +1,6 @@ --- title: "How to Analyze the Data" -description: "Learn how to analyze data presented in reports" +description: "Guide to analyzing data using dashboards in Access Analyzer" sidebar_position: 10 --- diff --git a/docs/accessanalyzer/1.0/reports-overview/my-reports.md b/docs/accessanalyzer/1.0/dashboards-reports/my-reports.md similarity index 82% rename from docs/accessanalyzer/1.0/reports-overview/my-reports.md rename to docs/accessanalyzer/1.0/dashboards-reports/my-reports.md index 26f3a69cab..5b232cd88a 100644 --- a/docs/accessanalyzer/1.0/reports-overview/my-reports.md +++ b/docs/accessanalyzer/1.0/dashboards-reports/my-reports.md @@ -1,7 +1,7 @@ --- title: "My Reports" description: "Custom saved reports" -sidebar_position: 60 +sidebar_position: 30 --- # My Reports diff --git a/docs/accessanalyzer/1.0/reports-overview/_category_.json b/docs/accessanalyzer/1.0/reports-overview/_category_.json deleted file mode 100644 index 6385d557da..0000000000 --- a/docs/accessanalyzer/1.0/reports-overview/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Reports Overview", - "position": 60, - "collapsed": true, - "collapsible": true -} diff --git a/docs/accessanalyzer/1.0/reports-overview/access.md b/docs/accessanalyzer/1.0/reports-overview/access.md deleted file mode 100644 index 9a04e9e2bb..0000000000 --- a/docs/accessanalyzer/1.0/reports-overview/access.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Access" -description: "Access reports overview" -sidebar_position: 20 ---- - -# Access - -*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/reports-overview/activity.md b/docs/accessanalyzer/1.0/reports-overview/activity.md deleted file mode 100644 index 81f8f5a9ca..0000000000 --- a/docs/accessanalyzer/1.0/reports-overview/activity.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Activity" -description: "Activity reports overview" -sidebar_position: 40 ---- - -# Activity - -*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/reports-overview/content.md b/docs/accessanalyzer/1.0/reports-overview/content.md deleted file mode 100644 index 855c66175a..0000000000 --- a/docs/accessanalyzer/1.0/reports-overview/content.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Content" -description: "Content reports overview" -sidebar_position: 30 ---- - -# Content - -*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/reports-overview/sensitive-data.md b/docs/accessanalyzer/1.0/reports-overview/sensitive-data.md deleted file mode 100644 index 6cdd68075f..0000000000 --- a/docs/accessanalyzer/1.0/reports-overview/sensitive-data.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Sensitive Data" -description: "Sensitive data reports overview" -sidebar_position: 50 ---- - -# Sensitive Data - -*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/scanners/best-practices.md b/docs/accessanalyzer/1.0/scanners/best-practices.md new file mode 100644 index 0000000000..01fabacf57 --- /dev/null +++ b/docs/accessanalyzer/1.0/scanners/best-practices.md @@ -0,0 +1,9 @@ +--- +title: "Best Practices" +description: "Best practices for configuring and running scanners in Access Analyzer" +sidebar_position: 20 +--- + +# Best Practices + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/scanners/overview.md b/docs/accessanalyzer/1.0/scanners/overview.md index d540453a0f..2c3087426a 100644 --- a/docs/accessanalyzer/1.0/scanners/overview.md +++ b/docs/accessanalyzer/1.0/scanners/overview.md @@ -1,9 +1,9 @@ --- -title: "Utilizing Scanners" +title: "Overview of Scanners" description: "Overview of scanner capabilities in Access Analyzer" sidebar_position: 10 --- -# Utilizing Scanners +# Overview of Scanners *Content coming soon.* From 3b0b55719242031880d5d9fb937e33b267e427c0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 15:46:31 +0000 Subject: [PATCH 05/62] build(deps): bump path-to-regexp Bumps the npm_and_yarn group with 1 update in the / directory: [path-to-regexp](https://github.com/pillarjs/path-to-regexp). Updates `path-to-regexp` from 0.1.12 to 0.1.13 - [Release notes](https://github.com/pillarjs/path-to-regexp/releases) - [Changelog](https://github.com/pillarjs/path-to-regexp/blob/v.0.1.13/History.md) - [Commits](https://github.com/pillarjs/path-to-regexp/compare/v0.1.12...v.0.1.13) --- updated-dependencies: - dependency-name: path-to-regexp dependency-version: 0.1.13 dependency-type: indirect dependency-group: npm_and_yarn ... Signed-off-by: dependabot[bot] --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9aac961d50..238a07a6d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10904,9 +10904,9 @@ "license": "MIT" }, "node_modules/express/node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", + "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", "license": "MIT" }, "node_modules/express/node_modules/qs": { From 3c56da110296366b20e91753e89363cd6ac4cc5a Mon Sep 17 00:00:00 2001 From: carlos-mejia_nwx Date: Mon, 6 Apr 2026 17:44:44 -0400 Subject: [PATCH 06/62] AA26: Structural restructure and naming improvements across documentation outline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Move System Requirements under Installation - Rename 'Start Collecting Data' → 'Quick Start Guides'; rename 4 scan guide pages to 'Scanning X' pattern - Convert scan guide pages to directories; nest source group wizard pages under each module - Rename 'Configurations and Making Changes' → 'Configuration'; 'Configuration Node' → 'Settings' - Reorder Settings pages to match UI sidebar (Service Accounts → Source Groups → Scans → Scan Executions → Sensitive Data → Users → Application Settings → System Logs → Notifications) - Remove Sources page (replaced by Source Groups) - Add Notifications stub page - Convert Sensitive Data to directory; move MIP Labeling as child page - Move Activity Monitor Integration under Quick Start Guides; rename to 'Activity Monitor Integration' - Rename 'Utilizing Scanners' → 'Scanners' - Fix duplicate connector titles (Entra ID and SharePoint Online both had 'Setting Up Requirements Within Entra') - Rename connector pages: Client Secret Configuration, Certificate Configuration, Entra Tenant Requirements, App Permissions in Entra - Populate connector prerequisite pages (AD, File Servers, Entra ID, SharePoint Online) with real content - Add Scanners overview page (Kubernetes-based architecture) - Naming/grammar: remove 'My First', 'Utilizing', 'Understanding the', 'How to', 'Setting up' prefixes across titles Co-Authored-By: Claude Sonnet 4.6 --- .../_category_.json | 6 -- .../1.0/configurations/_category_.json | 2 +- .../configuration-node/_category_.json | 2 +- .../application-settings.md | 2 +- .../configurations/configuration-node/logs.md | 8 +-- .../configuration-node/notifications.md | 9 +++ .../sensitive-data/_category_.json | 6 ++ .../sensitive-data/mip-labeling.md} | 6 +- .../overview.md} | 2 +- .../configuration-node/service-accounts.md | 2 +- .../configuration-node/source-groups.md | 2 +- .../configuration-node/sources.md | 9 --- .../configuration-node/users.md | 2 +- .../source-group-changes/_category_.json | 6 -- .../1.0/connectors/activedirectory.md | 48 ++++++-------- .../entra-id/app-registration-secret.md | 55 ++++++++++++++-- .../connectors/entra-id/entra-requirements.md | 66 ++++++++++++++++++- .../1.0/connectors/entra-id/overview.md | 4 +- .../1.0/connectors/file-servers/cifs.md | 63 +++++++++--------- .../sharepoint-online/azure-permissions.md | 65 ++++++++++++++++-- .../tenant-certificate-config.md | 58 ++++++++++++++-- .../how-to-analyze-reports.md | 9 --- .../how-to-analyze-the-data.md | 6 +- .../1.0/gettingstarted/_category_.json | 2 +- .../gettingstarted/active-directory-sync.md | 9 --- .../active-directory-sync/_category_.json | 6 ++ .../active-directory.md | 0 .../activity-data/_category_.json | 2 +- .../_category_.json | 6 ++ .../activity-monitor-integration/overview.md | 4 +- .../1.0/gettingstarted/entra-id-sync.md | 9 --- .../entra-id-sync/_category_.json | 6 ++ .../entra-id-sync}/entra-id.md | 0 .../1.0/gettingstarted/file-server-scans.md | 9 --- .../file-server-scans/_category_.json | 6 ++ .../file-server-scans}/file-server.md | 0 .../gettingstarted/first-service-account.md | 6 +- .../gettingstarted/sharepoint-online-scan.md | 9 --- .../sharepoint-online-scan/_category_.json | 6 ++ .../sharepoint-online.md | 0 .../1.0/gettingstarted/source-group-wizard.md | 6 +- .../1.0/install/_category_.json | 2 +- .../1.0/install/system/_category_.json | 6 ++ .../1.0/{ => install}/system/kubernetes.md | 0 .../1.0/{ => install}/system/network.md | 0 .../1.0/{ => install}/system/requirements.md | 0 .../1.0/scanners/_category_.json | 2 +- .../1.0/scanners/best-practices.md | 4 +- docs/accessanalyzer/1.0/scanners/overview.md | 27 +++++++- .../accessanalyzer/1.0/system/_category_.json | 10 --- 50 files changed, 392 insertions(+), 183 deletions(-) delete mode 100644 docs/accessanalyzer/1.0/activity-monitor-integration/_category_.json create mode 100644 docs/accessanalyzer/1.0/configurations/configuration-node/notifications.md create mode 100644 docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data/_category_.json rename docs/accessanalyzer/1.0/configurations/{mip-labeling-workflow.md => configuration-node/sensitive-data/mip-labeling.md} (58%) rename docs/accessanalyzer/1.0/configurations/configuration-node/{sensitive-data.md => sensitive-data/overview.md} (87%) delete mode 100644 docs/accessanalyzer/1.0/configurations/configuration-node/sources.md delete mode 100644 docs/accessanalyzer/1.0/configurations/source-group-changes/_category_.json delete mode 100644 docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-reports.md delete mode 100644 docs/accessanalyzer/1.0/gettingstarted/active-directory-sync.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/active-directory-sync/_category_.json rename docs/accessanalyzer/1.0/{configurations/source-group-changes => gettingstarted/active-directory-sync}/active-directory.md (100%) create mode 100644 docs/accessanalyzer/1.0/gettingstarted/activity-monitor-integration/_category_.json rename docs/accessanalyzer/1.0/{ => gettingstarted}/activity-monitor-integration/overview.md (58%) delete mode 100644 docs/accessanalyzer/1.0/gettingstarted/entra-id-sync.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/entra-id-sync/_category_.json rename docs/accessanalyzer/1.0/{configurations/source-group-changes => gettingstarted/entra-id-sync}/entra-id.md (100%) delete mode 100644 docs/accessanalyzer/1.0/gettingstarted/file-server-scans.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/file-server-scans/_category_.json rename docs/accessanalyzer/1.0/{configurations/source-group-changes => gettingstarted/file-server-scans}/file-server.md (100%) delete mode 100644 docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan/_category_.json rename docs/accessanalyzer/1.0/{configurations/source-group-changes => gettingstarted/sharepoint-online-scan}/sharepoint-online.md (100%) create mode 100644 docs/accessanalyzer/1.0/install/system/_category_.json rename docs/accessanalyzer/1.0/{ => install}/system/kubernetes.md (100%) rename docs/accessanalyzer/1.0/{ => install}/system/network.md (100%) rename docs/accessanalyzer/1.0/{ => install}/system/requirements.md (100%) delete mode 100644 docs/accessanalyzer/1.0/system/_category_.json diff --git a/docs/accessanalyzer/1.0/activity-monitor-integration/_category_.json b/docs/accessanalyzer/1.0/activity-monitor-integration/_category_.json deleted file mode 100644 index 463f554a78..0000000000 --- a/docs/accessanalyzer/1.0/activity-monitor-integration/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Setting up Activity Monitor Integration", - "position": 70, - "collapsed": true, - "collapsible": true -} diff --git a/docs/accessanalyzer/1.0/configurations/_category_.json b/docs/accessanalyzer/1.0/configurations/_category_.json index 9b86fef70b..76daee8c8e 100644 --- a/docs/accessanalyzer/1.0/configurations/_category_.json +++ b/docs/accessanalyzer/1.0/configurations/_category_.json @@ -1,5 +1,5 @@ { - "label": "Configurations and Making Changes", + "label": "Configuration", "position": 30, "collapsed": true, "collapsible": true diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/_category_.json b/docs/accessanalyzer/1.0/configurations/configuration-node/_category_.json index d5bca8fd28..70b787ca97 100644 --- a/docs/accessanalyzer/1.0/configurations/configuration-node/_category_.json +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/_category_.json @@ -1,5 +1,5 @@ { - "label": "Configuration Node", + "label": "Settings", "position": 20, "collapsed": true, "collapsible": true diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/application-settings.md b/docs/accessanalyzer/1.0/configurations/configuration-node/application-settings.md index 3aba566106..53382242e1 100644 --- a/docs/accessanalyzer/1.0/configurations/configuration-node/application-settings.md +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/application-settings.md @@ -1,7 +1,7 @@ --- title: "Application Settings" description: "Managing application settings in the Configuration node" -sidebar_position: 60 +sidebar_position: 80 --- # Application Settings diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/logs.md b/docs/accessanalyzer/1.0/configurations/configuration-node/logs.md index b28fd89fbe..88b30332d1 100644 --- a/docs/accessanalyzer/1.0/configurations/configuration-node/logs.md +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/logs.md @@ -1,9 +1,9 @@ --- -title: "Logs" -description: "Viewing logs in the Configuration node" -sidebar_position: 70 +title: "System Logs" +description: "Viewing system logs in Access Analyzer" +sidebar_position: 90 --- -# Logs +# System Logs *Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/notifications.md b/docs/accessanalyzer/1.0/configurations/configuration-node/notifications.md new file mode 100644 index 0000000000..40327ecad5 --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/notifications.md @@ -0,0 +1,9 @@ +--- +title: "Notifications" +description: "Configuring SMTP email notifications in Access Analyzer" +sidebar_position: 100 +--- + +# Notifications + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data/_category_.json b/docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data/_category_.json new file mode 100644 index 0000000000..7965ccfb43 --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Sensitive Data", + "position": 60, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/configurations/mip-labeling-workflow.md b/docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data/mip-labeling.md similarity index 58% rename from docs/accessanalyzer/1.0/configurations/mip-labeling-workflow.md rename to docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data/mip-labeling.md index b28cbd75aa..32bed90184 100644 --- a/docs/accessanalyzer/1.0/configurations/mip-labeling-workflow.md +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data/mip-labeling.md @@ -1,9 +1,9 @@ --- -title: "MIP Labeling and Workflow" +title: "MIP Labeling" description: "Microsoft Information Protection labeling and workflow configuration" -sidebar_position: 30 +sidebar_position: 10 --- -# MIP Labeling and Workflow +# MIP Labeling *Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data.md b/docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data/overview.md similarity index 87% rename from docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data.md rename to docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data/overview.md index 5c5453e455..b1535ed51f 100644 --- a/docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data.md +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data/overview.md @@ -1,7 +1,7 @@ --- title: "Sensitive Data" description: "Managing sensitive data settings in the Configuration node" -sidebar_position: 55 +sidebar_position: 5 --- # Sensitive Data diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/service-accounts.md b/docs/accessanalyzer/1.0/configurations/configuration-node/service-accounts.md index 7ce3e52660..956d4289c2 100644 --- a/docs/accessanalyzer/1.0/configurations/configuration-node/service-accounts.md +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/service-accounts.md @@ -1,7 +1,7 @@ --- title: "Service Accounts" description: "Managing service accounts in the Configuration node" -sidebar_position: 20 +sidebar_position: 10 --- # Service Accounts diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/source-groups.md b/docs/accessanalyzer/1.0/configurations/configuration-node/source-groups.md index d78d64468a..0eab251842 100644 --- a/docs/accessanalyzer/1.0/configurations/configuration-node/source-groups.md +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/source-groups.md @@ -1,7 +1,7 @@ --- title: "Source Groups" description: "Managing source groups in the Configuration node" -sidebar_position: 80 +sidebar_position: 20 --- # Source Groups diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/sources.md b/docs/accessanalyzer/1.0/configurations/configuration-node/sources.md deleted file mode 100644 index f99a43aef2..0000000000 --- a/docs/accessanalyzer/1.0/configurations/configuration-node/sources.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Sources" -description: "Managing sources in the Configuration node" -sidebar_position: 10 ---- - -# Sources - -*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/users.md b/docs/accessanalyzer/1.0/configurations/configuration-node/users.md index c5a0e8191a..50aa57edd1 100644 --- a/docs/accessanalyzer/1.0/configurations/configuration-node/users.md +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/users.md @@ -1,7 +1,7 @@ --- title: "Users" description: "Managing users in the Configuration node" -sidebar_position: 50 +sidebar_position: 70 --- # Users diff --git a/docs/accessanalyzer/1.0/configurations/source-group-changes/_category_.json b/docs/accessanalyzer/1.0/configurations/source-group-changes/_category_.json deleted file mode 100644 index 0b5c8adf0b..0000000000 --- a/docs/accessanalyzer/1.0/configurations/source-group-changes/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Making Changes to Source Group Wizards", - "position": 10, - "collapsed": true, - "collapsible": true -} diff --git a/docs/accessanalyzer/1.0/connectors/activedirectory.md b/docs/accessanalyzer/1.0/connectors/activedirectory.md index 2ef3c03a17..6a2949d4f2 100644 --- a/docs/accessanalyzer/1.0/connectors/activedirectory.md +++ b/docs/accessanalyzer/1.0/connectors/activedirectory.md @@ -6,40 +6,34 @@ sidebar_position: 30 # Active Directory -The Active Directory connector synchronizes users, groups, and group memberships from Active Directory into Access Analyzer. It uses the LDAP protocol for communication. +Access Analyzer scans Active Directory domains to enumerate users, groups, group memberships, permissions, and sensitive data. -## Network Requirements +## Supported Versions -| Port | Protocol | Direction | Description | -| --- | --- | --- | --- | -| 389 | TCP | Access Analyzer → Domain Controller | LDAP | -| 636 | TCP | Access Analyzer → Domain Controller | LDAPS (LDAP over SSL) | +- Windows Server 2016 and later +- Windows 2003 Forest level or higher -## Service Account Requirements +## Domain Controller Requirements -The connector requires a domain service account with the following: +The following must be installed on each domain controller to be scanned: -| Requirement | Details | -| --- | --- | -| **Account type** | Domain user account | -| **Authentication** | Username and password | -| **Minimum permissions** | Read access to directory objects (users, groups, OUs) | -| **Recommended group** | Domain Users (or equivalent read-only access) | +- .NET Framework 4.5 or later +- WINRM Service -:::note -The service account does not require Domain Admin or any write permissions. Read-only access to directory objects is sufficient for identity synchronization. -::: +## Permissions + +- Member of the **Domain Administrators** group -## Credential Type +:::info +Use Domain Administrator or Local Administrator privileges when running Access Analyzer against an Active Directory domain controller. +::: -| Field | Value | -| --- | --- | -| **Type** | Username / Password | -| **Username format** | `DOMAIN\username` or `username@domain.com` | +## Port Requirements -## Connector Capabilities +The following firewall ports are required for the Active Directory connector: -| Operation | Description | -| --- | --- | -| **Test connection** | Validates LDAP connectivity and credential authentication | -| **Sync** | Full synchronization of users, groups, and group memberships | +| Port | Protocol | Description | +| --- | --- | --- | +| 389 | TCP | LDAP | +| 135–139 | TCP | RPC | +| Randomly allocated high TCP ports | TCP | RPC dynamic ports | diff --git a/docs/accessanalyzer/1.0/connectors/entra-id/app-registration-secret.md b/docs/accessanalyzer/1.0/connectors/entra-id/app-registration-secret.md index 789a141560..4c6af18559 100644 --- a/docs/accessanalyzer/1.0/connectors/entra-id/app-registration-secret.md +++ b/docs/accessanalyzer/1.0/connectors/entra-id/app-registration-secret.md @@ -1,9 +1,56 @@ --- -title: "App Registration / Secret Configuration" -description: "Configure app registration and client secret for Entra ID" +title: "Client Secret Configuration" +description: "Configure a client secret for the Entra ID app registration" sidebar_position: 30 --- -# App Registration / Secret Configuration +# Client Secret Configuration -*Content coming soon.* +Access Analyzer authenticates to Microsoft Entra ID using a client secret. The client secret is generated within your registered Microsoft Entra ID application and provided to Access Analyzer when configuring the Entra ID connector. + +For state-in-time data collection, the registered application must also be assigned to the Global Administrator role. + +## Generate Client Secret Value + +**Step 1 –** Sign in to the [Microsoft Entra admin center](https://entra.microsoft.com/). + +**Step 2 –** Navigate to **Identity** > **Applications** > **App registrations**. + +**Step 3 –** Click the **All applications** tab and select your registered application. + +**Step 4 –** Click **Certificates & secrets** under the Manage section. + +**Step 5 –** On the **Client secrets** tab, click **New client secret**. + +**Step 6 –** Specify the following: + +- **Description** – Enter a description for the secret +- **Expires** – Select an expiration period + +**Step 7 –** Click **Add**. The client secret value is displayed in the **Value** column. + +:::warning +Copy the client secret value immediately. Once you navigate away from this page, the value cannot be retrieved and you will need to create a new secret. +::: + +## Assign Roles to the App + +The registered application must be assigned to the **Global Administrator** role for Entra ID state-in-time data collection. + +**Step 1 –** Sign in to the [Microsoft Entra admin center](https://entra.microsoft.com/). + +**Step 2 –** Navigate to **Identity** > **Applications** > **App registrations**. + +**Step 3 –** Click the **All applications** tab and select your registered application. + +**Step 4 –** Click **Roles and administrators** under the Manage section. + +**Step 5 –** On the All roles page, search for **Global Administrator**. + +**Step 6 –** Click the **Global Administrator** role. The Assignments page opens. + +**Step 7 –** Click **Add assignments** in the top toolbar. + +**Step 8 –** Search for and select your registered application. + +**Step 9 –** Click **Add**. The application is listed on the Assignments page. diff --git a/docs/accessanalyzer/1.0/connectors/entra-id/entra-requirements.md b/docs/accessanalyzer/1.0/connectors/entra-id/entra-requirements.md index b2b3c7917a..cc1ab4799f 100644 --- a/docs/accessanalyzer/1.0/connectors/entra-id/entra-requirements.md +++ b/docs/accessanalyzer/1.0/connectors/entra-id/entra-requirements.md @@ -1,9 +1,69 @@ --- -title: "Setting Up Requirements Within Entra" +title: "Entra Tenant Requirements" description: "Configure Entra ID requirements for connectivity" sidebar_position: 20 --- -# Setting Up Requirements Within Entra +# Entra Tenant Requirements -*Content coming soon.* +Access Analyzer connects to Microsoft Entra ID via a registered application using modern authentication, including support for multi-factor authentication (MFA). Access Analyzer accesses Entra ID through Microsoft Graph and other modern APIs, authenticated through a pre-configured Microsoft Entra ID application with the appropriate permissions. + +You must register a dedicated Microsoft Entra ID application for Access Analyzer and grant it the required permissions before adding Entra ID as a data source. + +:::note +A user account with the Global Administrator, Application Administrator, or Cloud Application Administrator role is required to register an application and grant admin consent for permissions. +::: + +:::note +The registered application must be assigned to the **Global Administrator** role for state-in-time data collection. +::: + +## Register an App in Microsoft Entra ID + +**Step 1 –** Sign in to the [Microsoft Entra admin center](https://entra.microsoft.com/). + +**Step 2 –** On the left navigation menu, navigate to **Identity** > **Applications** > **App registrations**. + +**Step 3 –** On the App registrations page, click **New registration** in the top toolbar. + +**Step 4 –** Specify the following on the Register an application page: + +- **Name** – Enter a display name for the application, for example, *Access Analyzer Entra ID* +- **Supported account types** – Select **Accounts in this organizational directory only** +- **Redirect URI (optional)** – Leave blank + +**Step 5 –** Click **Register**. + +The Overview page for the newly registered application opens. Note the following values — you will need them when configuring the Entra ID connector in Access Analyzer: + +- **Application (client) ID** +- **Directory (tenant) ID** + +## Grant Permissions to the App + +**Step 1 –** Sign in to the [Microsoft Entra admin center](https://entra.microsoft.com/). + +**Step 2 –** Navigate to **Identity** > **Applications** > **App registrations**. + +**Step 3 –** Click the **All applications** tab and select the application you registered. + +**Step 4 –** Click **API permissions** under the Manage section. + +**Step 5 –** Click **Add a permission**. The Request API permissions pane opens. + +**Step 6 –** Click an API to access its permissions, then click the **Application permissions** tab. + +**Step 7 –** Select the required permissions for each API (see table below). + +**Step 8 –** Click **Add Permissions**. + +**Step 9 –** Repeat Steps 6–8 for each API listed in the table below. + +**Step 10 –** Click **Grant admin consent for ``** to apply the permissions. + +### Required Permissions + +| API | Permission | Description | +| --- | --- | --- | +| Microsoft Graph | Directory.Read.All | Read directory data | +| Microsoft Graph | Policy.Read.All | Read your organization's policies (required for state-in-time reports) | diff --git a/docs/accessanalyzer/1.0/connectors/entra-id/overview.md b/docs/accessanalyzer/1.0/connectors/entra-id/overview.md index 11dfb77943..c807dd797d 100644 --- a/docs/accessanalyzer/1.0/connectors/entra-id/overview.md +++ b/docs/accessanalyzer/1.0/connectors/entra-id/overview.md @@ -1,10 +1,10 @@ --- -title: "Entra ID" +title: "Entra ID Requirements" description: "Azure App Registration, Graph API permissions, and OAuth2 credentials" sidebar_position: 40 --- -# Entra ID +# Entra ID Requirements The Entra ID connector validates connectivity to Microsoft Entra ID (formerly Azure Active Directory) using OAuth2 client credentials. diff --git a/docs/accessanalyzer/1.0/connectors/file-servers/cifs.md b/docs/accessanalyzer/1.0/connectors/file-servers/cifs.md index a5ade15dbd..e4ceab825e 100644 --- a/docs/accessanalyzer/1.0/connectors/file-servers/cifs.md +++ b/docs/accessanalyzer/1.0/connectors/file-servers/cifs.md @@ -6,47 +6,48 @@ sidebar_position: 10 # CIFS / SMB File Share -The CIFS/SMB connector scans Windows file shares to enumerate files, folders, and access permissions. It supports SMBv2 and SMBv3 protocols with concurrent scanning workers. +Access Analyzer scans Windows file servers to enumerate files, folders, access permissions, and sensitive data. -## Network Requirements +Scanning can be performed directly from the Access Analyzer service (local mode) or via Scanners — Kubernetes-deployed containers for distributed scanning of remote environments. See the [Utilizing Scanners](../../scanners/overview.md) section for details on Scanner architecture. -| Port | Protocol | Direction | Description | -| --- | --- | --- | --- | -| 445 | TCP | Access Analyzer → File Server | SMB file sharing | +## Permissions -## Service Account Requirements +Configure the service account credential with the following rights on the target Windows host(s): -| Requirement | Details | -| --- | --- | -| **Account type** | Domain or local user account on the file server | -| **Authentication** | Username and password | -| **Minimum permissions** | Read access and list permissions on target shares | -| **Domain** | Required if the file server is domain-joined | +- Group membership in both of the following local groups: + - **Power Users** + - **Backup Operators** +- Granted the **Backup files and directories** local policy privilege +- Granted the **Network access: Restrict clients allowed to make remote calls to SAM** Local Policies > Security Options privilege :::note -The service account needs read-only access to the shares and folders being scanned. It does not require write, modify, or administrative permissions. +To collect data on administrative shares and local policies for a Windows target, the credential must have group membership in the local **Administrators** group. ::: -## Credential Type +## Windows File System Clusters -| Field | Value | -| --- | --- | -| **Type** | Username / Password | -| **Username format** | `DOMAIN\username` or local account name | +When targeting a Windows File System Cluster, permissions must be configured on all nodes that comprise the cluster. Additional requirements beyond the standard permissions above: -## Connector Capabilities +- Remote Registry Service must be enabled on all cluster nodes +- Group membership in the local **Administrators** group +- Granted the **Log on as a batch** privilege -| Operation | Description | -| --- | --- | -| **Test connection** | Validates SMB connectivity and authentication | -| **Access scan** | Enumerates files, folders, and permissions with configurable worker concurrency (1–20) | -| **Get object** | Retrieves specific file or folder metadata | +:::note +Target the Windows Cluster File Server Role Server (the name clients connect to) when running a File System scan against a Windows File System Cluster. +::: + +## DFS Namespaces + +For domain-based DFS namespaces, the scan is configured to target the default domain controller for the domain. For standalone namespaces or multiple namespaces, target the server(s) hosting the namespace(s) directly. + +If the DFS hosting server is part of a Windows Cluster, the Windows File System Cluster requirements above also apply. + +## Sensitive Data Discovery + +Sensitive Data Discovery (SDD) scans require **.NET Framework 4.7.2 or later** installed on the server being scanned. -## Scan Configuration Options +## Port Requirements -| Option | Description | -| --- | --- | -| **Share filtering** | Include or exclude specific shares | -| **Scan depth** | Maximum folder depth to traverse | -| **Worker concurrency** | Number of parallel scanning threads (1–20) | -| **Pause / Resume** | Scans can be paused and resumed | +| Port | Protocol | Description | +| --- | --- | --- | +| 445 | TCP | SMB file sharing | diff --git a/docs/accessanalyzer/1.0/connectors/sharepoint-online/azure-permissions.md b/docs/accessanalyzer/1.0/connectors/sharepoint-online/azure-permissions.md index da88304a7a..b474d46faa 100644 --- a/docs/accessanalyzer/1.0/connectors/sharepoint-online/azure-permissions.md +++ b/docs/accessanalyzer/1.0/connectors/sharepoint-online/azure-permissions.md @@ -1,9 +1,66 @@ --- -title: "Setting Up Requirements Within Entra" -description: "Configure Entra ID requirements for SharePoint Online connectivity" +title: "App Permissions in Entra" +description: "Configure Entra ID app permissions for SharePoint Online connectivity" sidebar_position: 10 --- -# Setting Up Requirements Within Entra +# App Permissions in Entra -*Content coming soon.* +Access Analyzer connects to SharePoint Online via a Microsoft Entra ID registered application using modern authentication, including support for multi-factor authentication (MFA). Access Analyzer accesses SharePoint Online through Microsoft Graph and other modern APIs, authenticated through a pre-configured Microsoft Entra ID application with the appropriate permissions. + +You must register a dedicated Microsoft Entra ID application for Access Analyzer and grant it the required permissions before adding SharePoint Online as a data source. + +:::note +A user account with the Global Administrator, Application Administrator, or Cloud Application Administrator role is required to register an application and grant admin consent for permissions. +::: + +## Register an App in Microsoft Entra ID + +**Step 1 –** Sign in to the [Microsoft Entra admin center](https://entra.microsoft.com/). + +**Step 2 –** On the left navigation menu, navigate to **Identity** > **Applications** > **App registrations**. + +**Step 3 –** On the App registrations page, click **New registration** in the top toolbar. + +**Step 4 –** Specify the following on the Register an application page: + +- **Name** – Enter a display name for the application, for example, *Access Analyzer SharePoint Online* +- **Supported account types** – Select **Accounts in this organizational directory only** +- **Redirect URI (optional)** – Leave blank + +**Step 5 –** Click **Register**. + +The Overview page for the newly registered application opens. Note the following values — you will need them when configuring the SharePoint Online connector in Access Analyzer: + +- **Application (client) ID** +- **Directory (tenant) ID** + +## Grant Permissions to the App + +**Step 1 –** Sign in to the [Microsoft Entra admin center](https://entra.microsoft.com/). + +**Step 2 –** Navigate to **Identity** > **Applications** > **App registrations**. + +**Step 3 –** Click the **All applications** tab and select the application you registered. + +**Step 4 –** Click **API permissions** under the Manage section. + +**Step 5 –** Click **Add a permission**. The Request API permissions pane opens. + +**Step 6 –** Click an API to access its permissions, then click the **Application permissions** tab. + +**Step 7 –** Select the required permissions for each API (see table below). + +**Step 8 –** Click **Add Permissions**. + +**Step 9 –** Repeat Steps 6–8 for each API listed in the table below. + +**Step 10 –** Click **Grant admin consent for ``** to apply the permissions. + +### Required Permissions + +| API | Permission | Description | +| --- | --- | --- | +| Microsoft Graph | Sites.Read.All | Read items in all site collections | +| Microsoft Graph | Directory.Read.All | Read directory data | +| SharePoint | Sites.FullControl.All | Full control of all site collections (required for permissions and state-in-time reports) | diff --git a/docs/accessanalyzer/1.0/connectors/sharepoint-online/tenant-certificate-config.md b/docs/accessanalyzer/1.0/connectors/sharepoint-online/tenant-certificate-config.md index b702b388e5..2cdeeda634 100644 --- a/docs/accessanalyzer/1.0/connectors/sharepoint-online/tenant-certificate-config.md +++ b/docs/accessanalyzer/1.0/connectors/sharepoint-online/tenant-certificate-config.md @@ -1,9 +1,59 @@ --- -title: "App Registration / Certificate Configuration" -description: "Configure app registration and certificate authentication for SharePoint Online" +title: "Certificate Configuration" +description: "Configure certificate authentication for the SharePoint Online app registration" sidebar_position: 20 --- -# App Registration / Certificate Configuration +# Certificate Configuration -*Content coming soon.* +Access Analyzer uses two authentication methods depending on the SharePoint Online scan type: + +- **Client Secret** — used for access and permissions scanning +- **Certificate** — required for state-in-time (permissions snapshot) scanning + +Both are configured within your registered Microsoft Entra ID application. + +## Generate Client Secret Value + +**Step 1 –** Sign in to the [Microsoft Entra admin center](https://entra.microsoft.com/). + +**Step 2 –** Navigate to **Identity** > **Applications** > **App registrations**. + +**Step 3 –** Click the **All applications** tab and select your registered application. + +**Step 4 –** Click **Certificates & secrets** under the Manage section. + +**Step 5 –** On the **Client secrets** tab, click **New client secret**. + +**Step 6 –** Specify the following: + +- **Description** – Enter a description for the secret +- **Expires** – Select an expiration period + +**Step 7 –** Click **Add**. The client secret value is displayed in the **Value** column. + +:::warning +Copy the client secret value immediately. Once you navigate away from this page, the value cannot be retrieved and you will need to create a new secret. +::: + +## Upload a Certificate + +**Step 1 –** Sign in to the [Microsoft Entra admin center](https://entra.microsoft.com/). + +**Step 2 –** Navigate to **Identity** > **Applications** > **App registrations**. + +**Step 3 –** Click the **All applications** tab and select your registered application. + +**Step 4 –** Click **Certificates & secrets** under the Manage section. + +**Step 5 –** Click the **Certificates** tab. + +**Step 6 –** Click **Upload certificate**. + +**Step 7 –** Click the file icon next to the **Select a File** field. + +**Step 8 –** Browse to and select your certificate file (.cer or .pem), then click **Open**. + +**Step 9 –** Enter a description for the certificate. + +**Step 10 –** Click **Add**. The certificate is uploaded to the registered application. diff --git a/docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-reports.md b/docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-reports.md deleted file mode 100644 index 3070386614..0000000000 --- a/docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-reports.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "How to Analyze Reports" -description: "Guide to analyzing reports in Access Analyzer" -sidebar_position: 20 ---- - -# How to Analyze Reports - -*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-the-data.md b/docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-the-data.md index c6dbb29a93..de949167e3 100644 --- a/docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-the-data.md +++ b/docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-the-data.md @@ -1,9 +1,9 @@ --- -title: "How to Analyze the Data" -description: "Guide to analyzing data using dashboards in Access Analyzer" +title: "Analyzing Data and Reports" +description: "Guide to analyzing data and reports in Access Analyzer" sidebar_position: 10 --- -# How to Analyze the Data +# Analyzing Data and Reports *Content coming soon.* diff --git a/docs/accessanalyzer/1.0/gettingstarted/_category_.json b/docs/accessanalyzer/1.0/gettingstarted/_category_.json index 1c9c947f1d..3cefeac060 100644 --- a/docs/accessanalyzer/1.0/gettingstarted/_category_.json +++ b/docs/accessanalyzer/1.0/gettingstarted/_category_.json @@ -1,5 +1,5 @@ { - "label": "Start Collecting Data", + "label": "Quick Start Guides", "position": 20, "collapsed": true, "collapsible": true diff --git a/docs/accessanalyzer/1.0/gettingstarted/active-directory-sync.md b/docs/accessanalyzer/1.0/gettingstarted/active-directory-sync.md deleted file mode 100644 index 55ac39164a..0000000000 --- a/docs/accessanalyzer/1.0/gettingstarted/active-directory-sync.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Setting Up My First Active Directory Sync" -description: "Connect to Active Directory and sync users, groups, and organizational units" -sidebar_position: 20 ---- - -# Setting Up My First Active Directory Sync - -*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/gettingstarted/active-directory-sync/_category_.json b/docs/accessanalyzer/1.0/gettingstarted/active-directory-sync/_category_.json new file mode 100644 index 0000000000..fc2c06370c --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/active-directory-sync/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Scanning Active Directory", + "position": 20, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/configurations/source-group-changes/active-directory.md b/docs/accessanalyzer/1.0/gettingstarted/active-directory-sync/active-directory.md similarity index 100% rename from docs/accessanalyzer/1.0/configurations/source-group-changes/active-directory.md rename to docs/accessanalyzer/1.0/gettingstarted/active-directory-sync/active-directory.md diff --git a/docs/accessanalyzer/1.0/gettingstarted/activity-data/_category_.json b/docs/accessanalyzer/1.0/gettingstarted/activity-data/_category_.json index 188fff07b8..e008bc29bf 100644 --- a/docs/accessanalyzer/1.0/gettingstarted/activity-data/_category_.json +++ b/docs/accessanalyzer/1.0/gettingstarted/activity-data/_category_.json @@ -1,5 +1,5 @@ { - "label": "Start Collecting Activity Data", + "label": "Collecting Activity Data", "position": 70, "collapsed": true, "collapsible": true diff --git a/docs/accessanalyzer/1.0/gettingstarted/activity-monitor-integration/_category_.json b/docs/accessanalyzer/1.0/gettingstarted/activity-monitor-integration/_category_.json new file mode 100644 index 0000000000..130074f727 --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/activity-monitor-integration/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Activity Monitor Integration", + "position": 80, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/activity-monitor-integration/overview.md b/docs/accessanalyzer/1.0/gettingstarted/activity-monitor-integration/overview.md similarity index 58% rename from docs/accessanalyzer/1.0/activity-monitor-integration/overview.md rename to docs/accessanalyzer/1.0/gettingstarted/activity-monitor-integration/overview.md index 21dd6869e7..b76c72252c 100644 --- a/docs/accessanalyzer/1.0/activity-monitor-integration/overview.md +++ b/docs/accessanalyzer/1.0/gettingstarted/activity-monitor-integration/overview.md @@ -1,9 +1,9 @@ --- -title: "Setting up Activity Monitor Integration" +title: "Activity Monitor Integration" description: "Configure Activity Monitor integration with Access Analyzer" sidebar_position: 10 --- -# Setting up Activity Monitor Integration +# Activity Monitor Integration *Content coming soon.* diff --git a/docs/accessanalyzer/1.0/gettingstarted/entra-id-sync.md b/docs/accessanalyzer/1.0/gettingstarted/entra-id-sync.md deleted file mode 100644 index 031773a286..0000000000 --- a/docs/accessanalyzer/1.0/gettingstarted/entra-id-sync.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Setting Up My First Entra ID Sync" -description: "Connect to Microsoft Entra ID and sync cloud identities" -sidebar_position: 40 ---- - -# Setting Up My First Entra ID Sync - -*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/gettingstarted/entra-id-sync/_category_.json b/docs/accessanalyzer/1.0/gettingstarted/entra-id-sync/_category_.json new file mode 100644 index 0000000000..b4785d5d62 --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/entra-id-sync/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Scanning Entra ID", + "position": 40, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/configurations/source-group-changes/entra-id.md b/docs/accessanalyzer/1.0/gettingstarted/entra-id-sync/entra-id.md similarity index 100% rename from docs/accessanalyzer/1.0/configurations/source-group-changes/entra-id.md rename to docs/accessanalyzer/1.0/gettingstarted/entra-id-sync/entra-id.md diff --git a/docs/accessanalyzer/1.0/gettingstarted/file-server-scans.md b/docs/accessanalyzer/1.0/gettingstarted/file-server-scans.md deleted file mode 100644 index e99a39cb05..0000000000 --- a/docs/accessanalyzer/1.0/gettingstarted/file-server-scans.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Setting Up My First File Server Scans" -description: "Scan CIFS/SMB file shares for permissions and sensitive data" -sidebar_position: 30 ---- - -# Setting Up My First File Server Scans - -*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/gettingstarted/file-server-scans/_category_.json b/docs/accessanalyzer/1.0/gettingstarted/file-server-scans/_category_.json new file mode 100644 index 0000000000..4771d2c62e --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/file-server-scans/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Scanning File Servers", + "position": 30, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/configurations/source-group-changes/file-server.md b/docs/accessanalyzer/1.0/gettingstarted/file-server-scans/file-server.md similarity index 100% rename from docs/accessanalyzer/1.0/configurations/source-group-changes/file-server.md rename to docs/accessanalyzer/1.0/gettingstarted/file-server-scans/file-server.md diff --git a/docs/accessanalyzer/1.0/gettingstarted/first-service-account.md b/docs/accessanalyzer/1.0/gettingstarted/first-service-account.md index 124d4ff6bb..f58efefd6c 100644 --- a/docs/accessanalyzer/1.0/gettingstarted/first-service-account.md +++ b/docs/accessanalyzer/1.0/gettingstarted/first-service-account.md @@ -1,9 +1,9 @@ --- -title: "Setting Up My First Service Account" -description: "Create your first service account to connect to data sources" +title: "Setting Up a Service Account" +description: "Create a service account to connect to data sources" sidebar_position: 1 --- -# Setting Up My First Service Account +# Setting Up a Service Account *Content coming soon.* diff --git a/docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan.md b/docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan.md deleted file mode 100644 index e831c710c1..0000000000 --- a/docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Setting Up My First SharePoint Online Scan" -description: "Scan SharePoint Online sites for permissions and sensitive data" -sidebar_position: 50 ---- - -# Setting Up My First SharePoint Online Scan - -*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan/_category_.json b/docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan/_category_.json new file mode 100644 index 0000000000..23057cd793 --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Scanning SharePoint Online", + "position": 50, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/configurations/source-group-changes/sharepoint-online.md b/docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan/sharepoint-online.md similarity index 100% rename from docs/accessanalyzer/1.0/configurations/source-group-changes/sharepoint-online.md rename to docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan/sharepoint-online.md diff --git a/docs/accessanalyzer/1.0/gettingstarted/source-group-wizard.md b/docs/accessanalyzer/1.0/gettingstarted/source-group-wizard.md index a78450039d..ece698c97b 100644 --- a/docs/accessanalyzer/1.0/gettingstarted/source-group-wizard.md +++ b/docs/accessanalyzer/1.0/gettingstarted/source-group-wizard.md @@ -1,9 +1,9 @@ --- -title: "Understanding the Source Group Wizard Workflow" -description: "Learn how the Source Group Wizard guides you through connecting data sources and configuring scans" +title: "Source Group Wizard" +description: "How the Source Group Wizard guides you through connecting data sources and configuring scans" sidebar_position: 10 --- -# Understanding the Source Group Wizard Workflow +# Source Group Wizard *Content coming soon.* diff --git a/docs/accessanalyzer/1.0/install/_category_.json b/docs/accessanalyzer/1.0/install/_category_.json index edb97672cd..4ec6b4da75 100644 --- a/docs/accessanalyzer/1.0/install/_category_.json +++ b/docs/accessanalyzer/1.0/install/_category_.json @@ -1,6 +1,6 @@ { "label": "Installation", - "position": 16, + "position": 12, "collapsed": true, "collapsible": true } diff --git a/docs/accessanalyzer/1.0/install/system/_category_.json b/docs/accessanalyzer/1.0/install/system/_category_.json new file mode 100644 index 0000000000..3ca820d9a9 --- /dev/null +++ b/docs/accessanalyzer/1.0/install/system/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "System Requirements", + "position": 5, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/system/kubernetes.md b/docs/accessanalyzer/1.0/install/system/kubernetes.md similarity index 100% rename from docs/accessanalyzer/1.0/system/kubernetes.md rename to docs/accessanalyzer/1.0/install/system/kubernetes.md diff --git a/docs/accessanalyzer/1.0/system/network.md b/docs/accessanalyzer/1.0/install/system/network.md similarity index 100% rename from docs/accessanalyzer/1.0/system/network.md rename to docs/accessanalyzer/1.0/install/system/network.md diff --git a/docs/accessanalyzer/1.0/system/requirements.md b/docs/accessanalyzer/1.0/install/system/requirements.md similarity index 100% rename from docs/accessanalyzer/1.0/system/requirements.md rename to docs/accessanalyzer/1.0/install/system/requirements.md diff --git a/docs/accessanalyzer/1.0/scanners/_category_.json b/docs/accessanalyzer/1.0/scanners/_category_.json index 06591067c1..1f2304bcca 100644 --- a/docs/accessanalyzer/1.0/scanners/_category_.json +++ b/docs/accessanalyzer/1.0/scanners/_category_.json @@ -1,5 +1,5 @@ { - "label": "Utilizing Scanners", + "label": "Scanners", "position": 40, "collapsed": true, "collapsible": true diff --git a/docs/accessanalyzer/1.0/scanners/best-practices.md b/docs/accessanalyzer/1.0/scanners/best-practices.md index 01fabacf57..be4a4c9af6 100644 --- a/docs/accessanalyzer/1.0/scanners/best-practices.md +++ b/docs/accessanalyzer/1.0/scanners/best-practices.md @@ -1,9 +1,9 @@ --- -title: "Best Practices" +title: "Scanner Best Practices" description: "Best practices for configuring and running scanners in Access Analyzer" sidebar_position: 20 --- -# Best Practices +# Scanner Best Practices *Content coming soon.* diff --git a/docs/accessanalyzer/1.0/scanners/overview.md b/docs/accessanalyzer/1.0/scanners/overview.md index 2c3087426a..aa46eb4e4c 100644 --- a/docs/accessanalyzer/1.0/scanners/overview.md +++ b/docs/accessanalyzer/1.0/scanners/overview.md @@ -6,4 +6,29 @@ sidebar_position: 10 # Overview of Scanners -*Content coming soon.* +Scanners are lightweight, containerized agents used by Access Analyzer to perform distributed scanning of remote environments. They eliminate the need for a traditional proxy server by leveraging the Kubernetes infrastructure already powering Access Analyzer. + +## Supported Connectors + +Scanners are available for the following connectors only: + +- **Active Directory** +- **Windows File Servers** + +All other connectors (Entra ID, SharePoint Online) connect directly from the Access Analyzer service and do not use Scanners. + +## Architecture + +Scanners run as Kubernetes Jobs — short-lived containers that are deployed on demand to perform a scan and then terminated. This is a fundamentally different architecture from the Proxy and Applet modes available in legacy Netwrix Access Analyzer (NAA) v12. There is no persistent agent process and no manual applet deployment. + +| | Legacy NAA (v12) | Access Analyzer v1.0 | +| --- | --- | --- | +| **Distributed scanning** | Proxy server / Applet deployment | Kubernetes-deployed Scanner containers | +| **Deployment model** | Manual, persistent agent | On-demand Kubernetes Jobs | +| **Supported targets** | All file system types | Active Directory, Windows File Servers | + +## Pending Documentation + +:::note +Detailed Scanner configuration steps, deployment prerequisites, and architecture diagrams are pending input from the development team and will be added to this section prior to GA release. +::: diff --git a/docs/accessanalyzer/1.0/system/_category_.json b/docs/accessanalyzer/1.0/system/_category_.json deleted file mode 100644 index 684c03e579..0000000000 --- a/docs/accessanalyzer/1.0/system/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "System Requirements", - "position": 12, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "kubernetes" - } -} From b5f04719794189b60a7e6463ced8744b6d042a85 Mon Sep 17 00:00:00 2001 From: carlos-mejia_nwx Date: Tue, 7 Apr 2026 15:55:45 -0400 Subject: [PATCH 07/62] AA26: Update install guides with complete outbound domain list Expand the outbound endpoint tables in network.md and quickinstall.md from 4 incomplete rows to the full 18 required domains, grouped by category (Keygen/Licensing, GitHub, Docker Hub/CDN, K3s/Rancher) with When Required column. Add Required Domains section to quickinstall.md so the quick guide is self-contained. Co-Authored-By: Claude Sonnet 4.6 --- .../1.0/install/quickinstall.md | 27 ++++++++++++- .../1.0/install/system/network.md | 40 ++++++++++++++----- 2 files changed, 55 insertions(+), 12 deletions(-) diff --git a/docs/accessanalyzer/1.0/install/quickinstall.md b/docs/accessanalyzer/1.0/install/quickinstall.md index f3e9e35808..334c741b52 100644 --- a/docs/accessanalyzer/1.0/install/quickinstall.md +++ b/docs/accessanalyzer/1.0/install/quickinstall.md @@ -18,13 +18,38 @@ Before running the installer, confirm the following: | **Memory** | 8 GB RAM | 16 GB RAM | | **CPU** | 2 vCPUs | 4 vCPUs | | **Disk Space** | 20 GB free | 50 GB free | -| **Network** | Outbound HTTPS (port 443) | — | +| **Network** | Outbound HTTPS (port 443) to required endpoints — see [Required Domains](#required-domains) below | — | | **License** | Valid Netwrix license key | — | :::note If running on a hypervisor, configure **static memory allocation** (not dynamic/ballooned memory). See [Hardware and System Requirements](/docs/accessanalyzer/1_0/install/requirements) for hypervisor-specific instructions. ::: +## Required Domains + +All endpoints use HTTPS (port 443). The following domains must be reachable from the Access Analyzer server before installation. For firewall rule examples, see [Network and Port Requirements](/docs/accessanalyzer/1_0/install/system/network). + +| Endpoint | Category | Purpose | When Required | +| --- | --- | --- | --- | +| `api.keygen.sh` | Keygen / Licensing | License validation API | Installation and updates | +| `oci.pkg.keygen.sh` | Keygen / Licensing | Netwrix OCI registry — Helm charts and application images | Installation and updates | +| `raw.pkg.keygen.sh` | Keygen / Licensing | Installer script download | Installation and updates | +| `keygen-dist.c3c9112df8df715f42d1162cdce5dba1.r2.cloudflarestorage.com` | Keygen / Licensing CDN | Keygen artifact storage | Installation and updates | +| `api.github.com` | GitHub | GitHub API | Installation only | +| `github.com` | GitHub | Repository and release access | Installation only | +| `raw.githubusercontent.com` | GitHub | ArgoCD bootstrap manifests | Installation only | +| `release-assets.githubusercontent.com` | GitHub | Release asset downloads | Installation only | +| `pkg-containers.githubusercontent.com` | GitHub Container Registry | GitHub Packages CDN | Installation and updates | +| `ghcr.io` | GitHub Container Registry | Container images | Installation and updates | +| `auth.docker.io` | Docker Hub | Docker authentication | Installation and updates | +| `registry-1.docker.io` | Docker Hub | Container images | Installation and updates | +| `production.cloudflare.docker.com` | Docker CDN | Docker Hub CDN | Installation and updates | +| `docker-images-prod.6aa30f8b08e16409b46e0173d6de2f56.r2.cloudflarestorage.com` | Docker CDN | Docker image storage | Installation and updates | +| `d2glxqk2uabbnd.cloudfront.net` | Docker CDN | Docker image CDN | Installation and updates | +| `get.k3s.io` | K3s / Rancher | K3s installer download | Installation only | +| `rpm.rancher.io` | K3s / Rancher | K3s package repository | Installation only | +| `storage.googleapis.com` | K3s / Rancher | K3s artifact storage | Installation only | + ## Step 1: Prepare the System Update the operating system and verify internet connectivity: diff --git a/docs/accessanalyzer/1.0/install/system/network.md b/docs/accessanalyzer/1.0/install/system/network.md index f3c04090b4..8643ce201b 100644 --- a/docs/accessanalyzer/1.0/install/system/network.md +++ b/docs/accessanalyzer/1.0/install/system/network.md @@ -10,14 +10,28 @@ Access Analyzer requires outbound internet access during installation and operat ## Outbound Endpoints (Internet) -The following endpoints must be reachable over HTTPS (port 443): +All outbound traffic uses HTTPS (port 443). The following endpoints must be reachable from the Access Analyzer server: -| Endpoint | Purpose | When Required | -| --- | --- | --- | -| `get.k3s.io` | K3s installer download | Installation only | -| `raw.githubusercontent.com` | ArgoCD manifests | Installation only | -| `oci.pkg.keygen.sh` | Netwrix OCI registry (Helm charts, application images) | Installation and updates | -| `docker.io` / `docker.com` | Container base images | Installation and updates | +| Endpoint | Category | Purpose | When Required | +| --- | --- | --- | --- | +| `api.keygen.sh` | Keygen / Licensing | License validation API | Installation and updates | +| `oci.pkg.keygen.sh` | Keygen / Licensing | Netwrix OCI registry — Helm charts and application images | Installation and updates | +| `raw.pkg.keygen.sh` | Keygen / Licensing | Installer script download | Installation and updates | +| `keygen-dist.c3c9112df8df715f42d1162cdce5dba1.r2.cloudflarestorage.com` | Keygen / Licensing CDN | Keygen artifact storage | Installation and updates | +| `api.github.com` | GitHub | GitHub API | Installation only | +| `github.com` | GitHub | Repository and release access | Installation only | +| `raw.githubusercontent.com` | GitHub | ArgoCD bootstrap manifests | Installation only | +| `release-assets.githubusercontent.com` | GitHub | Release asset downloads | Installation only | +| `pkg-containers.githubusercontent.com` | GitHub Container Registry | GitHub Packages CDN | Installation and updates | +| `ghcr.io` | GitHub Container Registry | Container images | Installation and updates | +| `auth.docker.io` | Docker Hub | Docker authentication | Installation and updates | +| `registry-1.docker.io` | Docker Hub | Container images | Installation and updates | +| `production.cloudflare.docker.com` | Docker CDN | Docker Hub CDN | Installation and updates | +| `docker-images-prod.6aa30f8b08e16409b46e0173d6de2f56.r2.cloudflarestorage.com` | Docker CDN | Docker image storage | Installation and updates | +| `d2glxqk2uabbnd.cloudfront.net` | Docker CDN | Docker image CDN | Installation and updates | +| `get.k3s.io` | K3s / Rancher | K3s installer download | Installation only | +| `rpm.rancher.io` | K3s / Rancher | K3s package repository | Installation only | +| `storage.googleapis.com` | K3s / Rancher | K3s artifact storage | Installation only | ## Internal Ports @@ -41,13 +55,17 @@ All internal ports are bound to the local cluster network. Only port 443 (Traefi Depending on the connectors you configure, the Access Analyzer VM must also have outbound access to your data sources: -| Connector | Target Port | Protocol | Notes | +| Connector | Port | Protocol | Notes | | --- | --- | --- | --- | -| CIFS / SMB | 445 | TCP | SMB file shares | -| Active Directory | 389 / 636 | TCP | LDAP / LDAPS | +| CIFS / SMB | 445 | TCP | SMB file sharing | +| Active Directory | 389 | TCP | LDAP | +| Active Directory | 636 | TCP | LDAPS (encrypted) | +| Active Directory | 135–139 | TCP | RPC | +| Active Directory | 49152–65535 | TCP | RPC dynamic ports | | SharePoint Online | 443 | TCP | Microsoft Graph API | | Entra ID | 443 | TCP | Microsoft identity platform | -| Local Groups | 5985 / 5986 | TCP | WinRM (HTTP / HTTPS) | +| Local Groups | 5985 | TCP | WinRM (HTTP) | +| Local Groups | 5986 | TCP | WinRM (HTTPS) | ## Proxy Configuration From e575b02fedcd706227091306ba9e6e76faa7f18d Mon Sep 17 00:00:00 2001 From: carlos-mejia_nwx Date: Tue, 7 Apr 2026 22:44:28 -0400 Subject: [PATCH 08/62] Rename Access Analyzer version from 1.0 to 2601 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Rename docs/accessanalyzer/1.0/ → docs/accessanalyzer/2601/ - Rename sidebars/accessanalyzer/1.0.js → sidebars/accessanalyzer/2601.js - Update version/label/sidebarFile in src/config/products.js - Update kb_allowlist.json entry for accessanalyzer Co-Authored-By: Claude Sonnet 4.6 --- .../configurations/_category_.json | 0 .../configuration-node/_category_.json | 0 .../application-settings.md | 0 .../configurations/configuration-node/logs.md | 0 .../configuration-node/notifications.md | 0 .../configuration-node/scan-executions.md | 0 .../configuration-node/scans.md | 0 .../sensitive-data/_category_.json | 0 .../sensitive-data/mip-labeling.md | 0 .../sensitive-data/overview.md | 0 .../configuration-node/service-accounts.md | 0 .../configuration-node/source-groups.md | 0 .../configuration-node/users.md | 0 .../{1.0 => 2601}/connectors/_category_.json | 0 .../connectors/activedirectory.md | 0 .../connectors/entra-id/_category_.json | 0 .../entra-id/app-registration-secret.md | 0 .../connectors/entra-id/entra-requirements.md | 0 .../connectors/entra-id/overview.md | 0 .../connectors/file-servers/_category_.json | 0 .../connectors/file-servers/celerra.md | 0 .../connectors/file-servers/cifs.md | 0 .../connectors/file-servers/netapp.md | 0 .../connectors/file-servers/unity.md | 0 .../connectors/file-servers/vnx.md | 0 .../sharepoint-online/_category_.json | 0 .../sharepoint-online/azure-permissions.md | 0 .../tenant-certificate-config.md | 0 .../dashboards-reports/_category_.json | 0 .../_category_.json | 0 .../active-directory-dashboard/overview.md | 0 .../data-security-dashboard/_category_.json | 0 .../data-security-dashboard/activity.md | 0 .../data-security-dashboard/overview.md | 0 .../how-to-analyze-the-data.md | 0 .../dashboards-reports/my-reports.md | 0 .../gettingstarted/_category_.json | 0 .../active-directory-sync/_category_.json | 0 .../active-directory-sync/active-directory.md | 0 .../activity-data/_category_.json | 0 .../activity-data/file-server-activity.md | 0 .../_category_.json | 0 .../activity-monitor-integration/overview.md | 0 .../entra-id-sync/_category_.json | 0 .../gettingstarted/entra-id-sync/entra-id.md | 0 .../file-server-scans/_category_.json | 0 .../file-server-scans/file-server.md | 0 .../gettingstarted/first-service-account.md | 0 .../sharepoint-online-scan/_category_.json | 0 .../sharepoint-online.md | 0 .../gettingstarted/source-group-wizard.md | 0 docs/accessanalyzer/{1.0 => 2601}/index.md | 0 .../{1.0 => 2601}/install/_category_.json | 0 .../{1.0 => 2601}/install/postinstall.md | 0 .../{1.0 => 2601}/install/quickinstall.md | 0 .../{1.0 => 2601}/install/security.md | 0 .../install/system/_category_.json | 0 .../install/system/kubernetes.md | 0 .../{1.0 => 2601}/install/system/network.md | 63 ++++++++++++++++++- .../install/system/requirements.md | 14 +++-- .../{1.0 => 2601}/install/uninstall.md | 0 .../{1.0 => 2601}/overview/_category_.json | 0 .../{1.0 => 2601}/overview/keyconcepts.md | 0 .../{1.0 => 2601}/scanners/_category_.json | 0 .../{1.0 => 2601}/scanners/best-practices.md | 0 .../{1.0 => 2601}/scanners/overview.md | 0 kb_allowlist.json | 2 +- sidebars/accessanalyzer/{1.0.js => 2601.js} | 0 src/config/products.js | 6 +- 69 files changed, 73 insertions(+), 12 deletions(-) rename docs/accessanalyzer/{1.0 => 2601}/configurations/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/configurations/configuration-node/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/configurations/configuration-node/application-settings.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/configurations/configuration-node/logs.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/configurations/configuration-node/notifications.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/configurations/configuration-node/scan-executions.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/configurations/configuration-node/scans.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/configurations/configuration-node/sensitive-data/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/configurations/configuration-node/sensitive-data/mip-labeling.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/configurations/configuration-node/sensitive-data/overview.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/configurations/configuration-node/service-accounts.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/configurations/configuration-node/source-groups.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/configurations/configuration-node/users.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/connectors/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/connectors/activedirectory.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/connectors/entra-id/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/connectors/entra-id/app-registration-secret.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/connectors/entra-id/entra-requirements.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/connectors/entra-id/overview.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/connectors/file-servers/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/connectors/file-servers/celerra.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/connectors/file-servers/cifs.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/connectors/file-servers/netapp.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/connectors/file-servers/unity.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/connectors/file-servers/vnx.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/connectors/sharepoint-online/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/connectors/sharepoint-online/azure-permissions.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/connectors/sharepoint-online/tenant-certificate-config.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/dashboards-reports/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/dashboards-reports/active-directory-dashboard/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/dashboards-reports/active-directory-dashboard/overview.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/dashboards-reports/data-security-dashboard/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/dashboards-reports/data-security-dashboard/activity.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/dashboards-reports/data-security-dashboard/overview.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/dashboards-reports/how-to-analyze-the-data.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/dashboards-reports/my-reports.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/gettingstarted/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/gettingstarted/active-directory-sync/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/gettingstarted/active-directory-sync/active-directory.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/gettingstarted/activity-data/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/gettingstarted/activity-data/file-server-activity.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/gettingstarted/activity-monitor-integration/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/gettingstarted/activity-monitor-integration/overview.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/gettingstarted/entra-id-sync/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/gettingstarted/entra-id-sync/entra-id.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/gettingstarted/file-server-scans/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/gettingstarted/file-server-scans/file-server.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/gettingstarted/first-service-account.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/gettingstarted/sharepoint-online-scan/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/gettingstarted/sharepoint-online-scan/sharepoint-online.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/gettingstarted/source-group-wizard.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/index.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/install/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/install/postinstall.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/install/quickinstall.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/install/security.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/install/system/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/install/system/kubernetes.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/install/system/network.md (66%) rename docs/accessanalyzer/{1.0 => 2601}/install/system/requirements.md (75%) rename docs/accessanalyzer/{1.0 => 2601}/install/uninstall.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/overview/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/overview/keyconcepts.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/scanners/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/scanners/best-practices.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/scanners/overview.md (100%) rename sidebars/accessanalyzer/{1.0.js => 2601.js} (100%) diff --git a/docs/accessanalyzer/1.0/configurations/_category_.json b/docs/accessanalyzer/2601/configurations/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/configurations/_category_.json rename to docs/accessanalyzer/2601/configurations/_category_.json diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/_category_.json b/docs/accessanalyzer/2601/configurations/configuration-node/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/configurations/configuration-node/_category_.json rename to docs/accessanalyzer/2601/configurations/configuration-node/_category_.json diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/application-settings.md b/docs/accessanalyzer/2601/configurations/configuration-node/application-settings.md similarity index 100% rename from docs/accessanalyzer/1.0/configurations/configuration-node/application-settings.md rename to docs/accessanalyzer/2601/configurations/configuration-node/application-settings.md diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/logs.md b/docs/accessanalyzer/2601/configurations/configuration-node/logs.md similarity index 100% rename from docs/accessanalyzer/1.0/configurations/configuration-node/logs.md rename to docs/accessanalyzer/2601/configurations/configuration-node/logs.md diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/notifications.md b/docs/accessanalyzer/2601/configurations/configuration-node/notifications.md similarity index 100% rename from docs/accessanalyzer/1.0/configurations/configuration-node/notifications.md rename to docs/accessanalyzer/2601/configurations/configuration-node/notifications.md diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/scan-executions.md b/docs/accessanalyzer/2601/configurations/configuration-node/scan-executions.md similarity index 100% rename from docs/accessanalyzer/1.0/configurations/configuration-node/scan-executions.md rename to docs/accessanalyzer/2601/configurations/configuration-node/scan-executions.md diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/scans.md b/docs/accessanalyzer/2601/configurations/configuration-node/scans.md similarity index 100% rename from docs/accessanalyzer/1.0/configurations/configuration-node/scans.md rename to docs/accessanalyzer/2601/configurations/configuration-node/scans.md diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data/_category_.json b/docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data/_category_.json rename to docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/_category_.json diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data/mip-labeling.md b/docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/mip-labeling.md similarity index 100% rename from docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data/mip-labeling.md rename to docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/mip-labeling.md diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data/overview.md b/docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/overview.md similarity index 100% rename from docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data/overview.md rename to docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/overview.md diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/service-accounts.md b/docs/accessanalyzer/2601/configurations/configuration-node/service-accounts.md similarity index 100% rename from docs/accessanalyzer/1.0/configurations/configuration-node/service-accounts.md rename to docs/accessanalyzer/2601/configurations/configuration-node/service-accounts.md diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/source-groups.md b/docs/accessanalyzer/2601/configurations/configuration-node/source-groups.md similarity index 100% rename from docs/accessanalyzer/1.0/configurations/configuration-node/source-groups.md rename to docs/accessanalyzer/2601/configurations/configuration-node/source-groups.md diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/users.md b/docs/accessanalyzer/2601/configurations/configuration-node/users.md similarity index 100% rename from docs/accessanalyzer/1.0/configurations/configuration-node/users.md rename to docs/accessanalyzer/2601/configurations/configuration-node/users.md diff --git a/docs/accessanalyzer/1.0/connectors/_category_.json b/docs/accessanalyzer/2601/connectors/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/connectors/_category_.json rename to docs/accessanalyzer/2601/connectors/_category_.json diff --git a/docs/accessanalyzer/1.0/connectors/activedirectory.md b/docs/accessanalyzer/2601/connectors/activedirectory.md similarity index 100% rename from docs/accessanalyzer/1.0/connectors/activedirectory.md rename to docs/accessanalyzer/2601/connectors/activedirectory.md diff --git a/docs/accessanalyzer/1.0/connectors/entra-id/_category_.json b/docs/accessanalyzer/2601/connectors/entra-id/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/connectors/entra-id/_category_.json rename to docs/accessanalyzer/2601/connectors/entra-id/_category_.json diff --git a/docs/accessanalyzer/1.0/connectors/entra-id/app-registration-secret.md b/docs/accessanalyzer/2601/connectors/entra-id/app-registration-secret.md similarity index 100% rename from docs/accessanalyzer/1.0/connectors/entra-id/app-registration-secret.md rename to docs/accessanalyzer/2601/connectors/entra-id/app-registration-secret.md diff --git a/docs/accessanalyzer/1.0/connectors/entra-id/entra-requirements.md b/docs/accessanalyzer/2601/connectors/entra-id/entra-requirements.md similarity index 100% rename from docs/accessanalyzer/1.0/connectors/entra-id/entra-requirements.md rename to docs/accessanalyzer/2601/connectors/entra-id/entra-requirements.md diff --git a/docs/accessanalyzer/1.0/connectors/entra-id/overview.md b/docs/accessanalyzer/2601/connectors/entra-id/overview.md similarity index 100% rename from docs/accessanalyzer/1.0/connectors/entra-id/overview.md rename to docs/accessanalyzer/2601/connectors/entra-id/overview.md diff --git a/docs/accessanalyzer/1.0/connectors/file-servers/_category_.json b/docs/accessanalyzer/2601/connectors/file-servers/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/connectors/file-servers/_category_.json rename to docs/accessanalyzer/2601/connectors/file-servers/_category_.json diff --git a/docs/accessanalyzer/1.0/connectors/file-servers/celerra.md b/docs/accessanalyzer/2601/connectors/file-servers/celerra.md similarity index 100% rename from docs/accessanalyzer/1.0/connectors/file-servers/celerra.md rename to docs/accessanalyzer/2601/connectors/file-servers/celerra.md diff --git a/docs/accessanalyzer/1.0/connectors/file-servers/cifs.md b/docs/accessanalyzer/2601/connectors/file-servers/cifs.md similarity index 100% rename from docs/accessanalyzer/1.0/connectors/file-servers/cifs.md rename to docs/accessanalyzer/2601/connectors/file-servers/cifs.md diff --git a/docs/accessanalyzer/1.0/connectors/file-servers/netapp.md b/docs/accessanalyzer/2601/connectors/file-servers/netapp.md similarity index 100% rename from docs/accessanalyzer/1.0/connectors/file-servers/netapp.md rename to docs/accessanalyzer/2601/connectors/file-servers/netapp.md diff --git a/docs/accessanalyzer/1.0/connectors/file-servers/unity.md b/docs/accessanalyzer/2601/connectors/file-servers/unity.md similarity index 100% rename from docs/accessanalyzer/1.0/connectors/file-servers/unity.md rename to docs/accessanalyzer/2601/connectors/file-servers/unity.md diff --git a/docs/accessanalyzer/1.0/connectors/file-servers/vnx.md b/docs/accessanalyzer/2601/connectors/file-servers/vnx.md similarity index 100% rename from docs/accessanalyzer/1.0/connectors/file-servers/vnx.md rename to docs/accessanalyzer/2601/connectors/file-servers/vnx.md diff --git a/docs/accessanalyzer/1.0/connectors/sharepoint-online/_category_.json b/docs/accessanalyzer/2601/connectors/sharepoint-online/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/connectors/sharepoint-online/_category_.json rename to docs/accessanalyzer/2601/connectors/sharepoint-online/_category_.json diff --git a/docs/accessanalyzer/1.0/connectors/sharepoint-online/azure-permissions.md b/docs/accessanalyzer/2601/connectors/sharepoint-online/azure-permissions.md similarity index 100% rename from docs/accessanalyzer/1.0/connectors/sharepoint-online/azure-permissions.md rename to docs/accessanalyzer/2601/connectors/sharepoint-online/azure-permissions.md diff --git a/docs/accessanalyzer/1.0/connectors/sharepoint-online/tenant-certificate-config.md b/docs/accessanalyzer/2601/connectors/sharepoint-online/tenant-certificate-config.md similarity index 100% rename from docs/accessanalyzer/1.0/connectors/sharepoint-online/tenant-certificate-config.md rename to docs/accessanalyzer/2601/connectors/sharepoint-online/tenant-certificate-config.md diff --git a/docs/accessanalyzer/1.0/dashboards-reports/_category_.json b/docs/accessanalyzer/2601/dashboards-reports/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/dashboards-reports/_category_.json rename to docs/accessanalyzer/2601/dashboards-reports/_category_.json diff --git a/docs/accessanalyzer/1.0/dashboards-reports/active-directory-dashboard/_category_.json b/docs/accessanalyzer/2601/dashboards-reports/active-directory-dashboard/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/dashboards-reports/active-directory-dashboard/_category_.json rename to docs/accessanalyzer/2601/dashboards-reports/active-directory-dashboard/_category_.json diff --git a/docs/accessanalyzer/1.0/dashboards-reports/active-directory-dashboard/overview.md b/docs/accessanalyzer/2601/dashboards-reports/active-directory-dashboard/overview.md similarity index 100% rename from docs/accessanalyzer/1.0/dashboards-reports/active-directory-dashboard/overview.md rename to docs/accessanalyzer/2601/dashboards-reports/active-directory-dashboard/overview.md diff --git a/docs/accessanalyzer/1.0/dashboards-reports/data-security-dashboard/_category_.json b/docs/accessanalyzer/2601/dashboards-reports/data-security-dashboard/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/dashboards-reports/data-security-dashboard/_category_.json rename to docs/accessanalyzer/2601/dashboards-reports/data-security-dashboard/_category_.json diff --git a/docs/accessanalyzer/1.0/dashboards-reports/data-security-dashboard/activity.md b/docs/accessanalyzer/2601/dashboards-reports/data-security-dashboard/activity.md similarity index 100% rename from docs/accessanalyzer/1.0/dashboards-reports/data-security-dashboard/activity.md rename to docs/accessanalyzer/2601/dashboards-reports/data-security-dashboard/activity.md diff --git a/docs/accessanalyzer/1.0/dashboards-reports/data-security-dashboard/overview.md b/docs/accessanalyzer/2601/dashboards-reports/data-security-dashboard/overview.md similarity index 100% rename from docs/accessanalyzer/1.0/dashboards-reports/data-security-dashboard/overview.md rename to docs/accessanalyzer/2601/dashboards-reports/data-security-dashboard/overview.md diff --git a/docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-the-data.md b/docs/accessanalyzer/2601/dashboards-reports/how-to-analyze-the-data.md similarity index 100% rename from docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-the-data.md rename to docs/accessanalyzer/2601/dashboards-reports/how-to-analyze-the-data.md diff --git a/docs/accessanalyzer/1.0/dashboards-reports/my-reports.md b/docs/accessanalyzer/2601/dashboards-reports/my-reports.md similarity index 100% rename from docs/accessanalyzer/1.0/dashboards-reports/my-reports.md rename to docs/accessanalyzer/2601/dashboards-reports/my-reports.md diff --git a/docs/accessanalyzer/1.0/gettingstarted/_category_.json b/docs/accessanalyzer/2601/gettingstarted/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/gettingstarted/_category_.json rename to docs/accessanalyzer/2601/gettingstarted/_category_.json diff --git a/docs/accessanalyzer/1.0/gettingstarted/active-directory-sync/_category_.json b/docs/accessanalyzer/2601/gettingstarted/active-directory-sync/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/gettingstarted/active-directory-sync/_category_.json rename to docs/accessanalyzer/2601/gettingstarted/active-directory-sync/_category_.json diff --git a/docs/accessanalyzer/1.0/gettingstarted/active-directory-sync/active-directory.md b/docs/accessanalyzer/2601/gettingstarted/active-directory-sync/active-directory.md similarity index 100% rename from docs/accessanalyzer/1.0/gettingstarted/active-directory-sync/active-directory.md rename to docs/accessanalyzer/2601/gettingstarted/active-directory-sync/active-directory.md diff --git a/docs/accessanalyzer/1.0/gettingstarted/activity-data/_category_.json b/docs/accessanalyzer/2601/gettingstarted/activity-data/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/gettingstarted/activity-data/_category_.json rename to docs/accessanalyzer/2601/gettingstarted/activity-data/_category_.json diff --git a/docs/accessanalyzer/1.0/gettingstarted/activity-data/file-server-activity.md b/docs/accessanalyzer/2601/gettingstarted/activity-data/file-server-activity.md similarity index 100% rename from docs/accessanalyzer/1.0/gettingstarted/activity-data/file-server-activity.md rename to docs/accessanalyzer/2601/gettingstarted/activity-data/file-server-activity.md diff --git a/docs/accessanalyzer/1.0/gettingstarted/activity-monitor-integration/_category_.json b/docs/accessanalyzer/2601/gettingstarted/activity-monitor-integration/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/gettingstarted/activity-monitor-integration/_category_.json rename to docs/accessanalyzer/2601/gettingstarted/activity-monitor-integration/_category_.json diff --git a/docs/accessanalyzer/1.0/gettingstarted/activity-monitor-integration/overview.md b/docs/accessanalyzer/2601/gettingstarted/activity-monitor-integration/overview.md similarity index 100% rename from docs/accessanalyzer/1.0/gettingstarted/activity-monitor-integration/overview.md rename to docs/accessanalyzer/2601/gettingstarted/activity-monitor-integration/overview.md diff --git a/docs/accessanalyzer/1.0/gettingstarted/entra-id-sync/_category_.json b/docs/accessanalyzer/2601/gettingstarted/entra-id-sync/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/gettingstarted/entra-id-sync/_category_.json rename to docs/accessanalyzer/2601/gettingstarted/entra-id-sync/_category_.json diff --git a/docs/accessanalyzer/1.0/gettingstarted/entra-id-sync/entra-id.md b/docs/accessanalyzer/2601/gettingstarted/entra-id-sync/entra-id.md similarity index 100% rename from docs/accessanalyzer/1.0/gettingstarted/entra-id-sync/entra-id.md rename to docs/accessanalyzer/2601/gettingstarted/entra-id-sync/entra-id.md diff --git a/docs/accessanalyzer/1.0/gettingstarted/file-server-scans/_category_.json b/docs/accessanalyzer/2601/gettingstarted/file-server-scans/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/gettingstarted/file-server-scans/_category_.json rename to docs/accessanalyzer/2601/gettingstarted/file-server-scans/_category_.json diff --git a/docs/accessanalyzer/1.0/gettingstarted/file-server-scans/file-server.md b/docs/accessanalyzer/2601/gettingstarted/file-server-scans/file-server.md similarity index 100% rename from docs/accessanalyzer/1.0/gettingstarted/file-server-scans/file-server.md rename to docs/accessanalyzer/2601/gettingstarted/file-server-scans/file-server.md diff --git a/docs/accessanalyzer/1.0/gettingstarted/first-service-account.md b/docs/accessanalyzer/2601/gettingstarted/first-service-account.md similarity index 100% rename from docs/accessanalyzer/1.0/gettingstarted/first-service-account.md rename to docs/accessanalyzer/2601/gettingstarted/first-service-account.md diff --git a/docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan/_category_.json b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online-scan/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan/_category_.json rename to docs/accessanalyzer/2601/gettingstarted/sharepoint-online-scan/_category_.json diff --git a/docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan/sharepoint-online.md b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online-scan/sharepoint-online.md similarity index 100% rename from docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan/sharepoint-online.md rename to docs/accessanalyzer/2601/gettingstarted/sharepoint-online-scan/sharepoint-online.md diff --git a/docs/accessanalyzer/1.0/gettingstarted/source-group-wizard.md b/docs/accessanalyzer/2601/gettingstarted/source-group-wizard.md similarity index 100% rename from docs/accessanalyzer/1.0/gettingstarted/source-group-wizard.md rename to docs/accessanalyzer/2601/gettingstarted/source-group-wizard.md diff --git a/docs/accessanalyzer/1.0/index.md b/docs/accessanalyzer/2601/index.md similarity index 100% rename from docs/accessanalyzer/1.0/index.md rename to docs/accessanalyzer/2601/index.md diff --git a/docs/accessanalyzer/1.0/install/_category_.json b/docs/accessanalyzer/2601/install/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/install/_category_.json rename to docs/accessanalyzer/2601/install/_category_.json diff --git a/docs/accessanalyzer/1.0/install/postinstall.md b/docs/accessanalyzer/2601/install/postinstall.md similarity index 100% rename from docs/accessanalyzer/1.0/install/postinstall.md rename to docs/accessanalyzer/2601/install/postinstall.md diff --git a/docs/accessanalyzer/1.0/install/quickinstall.md b/docs/accessanalyzer/2601/install/quickinstall.md similarity index 100% rename from docs/accessanalyzer/1.0/install/quickinstall.md rename to docs/accessanalyzer/2601/install/quickinstall.md diff --git a/docs/accessanalyzer/1.0/install/security.md b/docs/accessanalyzer/2601/install/security.md similarity index 100% rename from docs/accessanalyzer/1.0/install/security.md rename to docs/accessanalyzer/2601/install/security.md diff --git a/docs/accessanalyzer/1.0/install/system/_category_.json b/docs/accessanalyzer/2601/install/system/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/install/system/_category_.json rename to docs/accessanalyzer/2601/install/system/_category_.json diff --git a/docs/accessanalyzer/1.0/install/system/kubernetes.md b/docs/accessanalyzer/2601/install/system/kubernetes.md similarity index 100% rename from docs/accessanalyzer/1.0/install/system/kubernetes.md rename to docs/accessanalyzer/2601/install/system/kubernetes.md diff --git a/docs/accessanalyzer/1.0/install/system/network.md b/docs/accessanalyzer/2601/install/system/network.md similarity index 66% rename from docs/accessanalyzer/1.0/install/system/network.md rename to docs/accessanalyzer/2601/install/system/network.md index 8643ce201b..435e186cc3 100644 --- a/docs/accessanalyzer/1.0/install/system/network.md +++ b/docs/accessanalyzer/2601/install/system/network.md @@ -74,9 +74,68 @@ If outbound traffic is routed through a proxy, set the following environment var ```bash export HTTP_PROXY="http://:" export HTTPS_PROXY="http://:" -export NO_PROXY="localhost,127.0.0.1,10.0.0.0/8" +export NO_PROXY="localhost,127.0.0.1,.svc,.cluster.local,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16" ``` +## Antivirus Exclusions + +If an endpoint detection or antivirus product is running on the Access Analyzer host, configure exclusions for the following paths before installation. The installer's preflight checks detect common products (CrowdStrike Falcon, SentinelOne, Sophos, and others) and will prompt you to confirm exclusions are in place. + +| Path | Reason | +| --- | --- | +| `/var/lib/rancher/` | K3s runtime data | +| `/var/lib/containerd/` | Container image layers | +| `/run/k3s/` | K3s socket and runtime files | +| `/usr/local/bin/k3s` | K3s binary | + +:::note +Setting `SKIP_AV_CHECK=true` before running the installer bypasses the antivirus detection prompt, but does not configure exclusions automatically. Configure exclusions manually before running the installer. +::: + ## Firewall Configuration -See [Network Configuration](/docs/accessanalyzer/1_0/install/network) for firewall rule examples for Azure, AWS, and on-premises environments. +Allow outbound HTTPS (port 443) to all endpoints listed in the [Outbound Endpoints](#outbound-endpoints-internet) table above. The examples below show how to configure this on common platforms. + +### Azure (NSG Rule) + +```bash +az network nsg rule create \ + --resource-group \ + --nsg-name \ + --name AllowOutboundHTTPS \ + --priority 100 \ + --direction Outbound \ + --access Allow \ + --protocol Tcp \ + --destination-port-ranges 443 +``` + +### AWS (EC2 Security Group) + +```bash +aws ec2 authorize-security-group-egress \ + --group-id \ + --protocol tcp \ + --port 443 \ + --cidr 0.0.0.0/0 +``` + +### On-Premises (ufw) + +```bash +sudo ufw allow out 443/tcp +sudo ufw reload +``` + +### Verify Connectivity + +After configuring firewall rules, verify that the required endpoints are reachable from the Access Analyzer server: + +```bash +curl -I https://oci.pkg.keygen.sh +curl -I https://ghcr.io +curl -I https://registry-1.docker.io +curl -I https://get.k3s.io +``` + +All commands should return an HTTP response (2xx or 3xx). A connection timeout or refusal indicates a firewall rule is blocking the endpoint. diff --git a/docs/accessanalyzer/1.0/install/system/requirements.md b/docs/accessanalyzer/2601/install/system/requirements.md similarity index 75% rename from docs/accessanalyzer/1.0/install/system/requirements.md rename to docs/accessanalyzer/2601/install/system/requirements.md index 885dc0fdaf..20dfd2437e 100644 --- a/docs/accessanalyzer/1.0/install/system/requirements.md +++ b/docs/accessanalyzer/2601/install/system/requirements.md @@ -10,14 +10,16 @@ Access Analyzer is deployed on a single Linux virtual machine. The installer run ## Deployment Sizing -| Size | CPU | Memory | Disk | Use Case | -| --- | --- | --- | --- | --- | -| **Small** | 2 vCPUs (4 recommended) | 8 GB (16 GB recommended) | 20 GB free (50 GB recommended) | Evaluation and small environments | -| **Medium** | 8 vCPUs | 32 GB | 100 GB SSD | Mid-size environments | -| **Large** | 16 vCPUs | 64 GB | 500 GB SSD | Large enterprise environments | +Use the **Minimum** specifications for evaluation and lab deployments. Use the **Production Recommended** specifications for customer-facing or enterprise deployments. The installer enforces the minimum thresholds — preflight checks will fail if the system falls below them. + +| Size | Min CPU | Min Memory | Min Disk | Prod CPU | Prod Memory | Prod Disk | Typical Environment | +| --- | --- | --- | --- | --- | --- | --- | --- | +| **Small** | 2 vCPUs | 8 GB | 20 GB free | 8 cores | 32 GB | 1 TB SSD | Evaluation, pilots, up to ~1,000 assets | +| **Medium** | 4 vCPUs | 16 GB | 50 GB free | 16 cores | 64 GB | 1 TB SSD | Up to ~5,000 assets | +| **Large** | 8 vCPUs | 32 GB | 100 GB free | 32 cores | 128 GB | 1 TB SSD | 5,000+ assets / enterprise | :::note -The `--size` flag scales memory requirements by the specified multiplier. For example, `--size 2` doubles the minimum and recommended memory thresholds. See [Environment Variables](/docs/accessanalyzer/1_0/install/environmentvariables) for details. +The `--size` flag scales memory thresholds by the specified multiplier. For example, `--size 2` doubles the minimum and recommended memory requirements enforced by the preflight checks. ::: ## Disk Space Requirements diff --git a/docs/accessanalyzer/1.0/install/uninstall.md b/docs/accessanalyzer/2601/install/uninstall.md similarity index 100% rename from docs/accessanalyzer/1.0/install/uninstall.md rename to docs/accessanalyzer/2601/install/uninstall.md diff --git a/docs/accessanalyzer/1.0/overview/_category_.json b/docs/accessanalyzer/2601/overview/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/overview/_category_.json rename to docs/accessanalyzer/2601/overview/_category_.json diff --git a/docs/accessanalyzer/1.0/overview/keyconcepts.md b/docs/accessanalyzer/2601/overview/keyconcepts.md similarity index 100% rename from docs/accessanalyzer/1.0/overview/keyconcepts.md rename to docs/accessanalyzer/2601/overview/keyconcepts.md diff --git a/docs/accessanalyzer/1.0/scanners/_category_.json b/docs/accessanalyzer/2601/scanners/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/scanners/_category_.json rename to docs/accessanalyzer/2601/scanners/_category_.json diff --git a/docs/accessanalyzer/1.0/scanners/best-practices.md b/docs/accessanalyzer/2601/scanners/best-practices.md similarity index 100% rename from docs/accessanalyzer/1.0/scanners/best-practices.md rename to docs/accessanalyzer/2601/scanners/best-practices.md diff --git a/docs/accessanalyzer/1.0/scanners/overview.md b/docs/accessanalyzer/2601/scanners/overview.md similarity index 100% rename from docs/accessanalyzer/1.0/scanners/overview.md rename to docs/accessanalyzer/2601/scanners/overview.md diff --git a/kb_allowlist.json b/kb_allowlist.json index 356ff9e772..55782a0c91 100644 --- a/kb_allowlist.json +++ b/kb_allowlist.json @@ -3,7 +3,7 @@ "current" ], "accessanalyzer": [ - "1.0", + "2601", "11.6", "12.0" ], diff --git a/sidebars/accessanalyzer/1.0.js b/sidebars/accessanalyzer/2601.js similarity index 100% rename from sidebars/accessanalyzer/1.0.js rename to sidebars/accessanalyzer/2601.js diff --git a/src/config/products.js b/src/config/products.js index 730b361205..2534178506 100644 --- a/src/config/products.js +++ b/src/config/products.js @@ -61,10 +61,10 @@ export const PRODUCTS = [ icon: '', versions: [ { - version: '1.0', - label: '1.0', + version: '2601', + label: '2601', isLatest: false, - sidebarFile: './sidebars/accessanalyzer/1.0.js', + sidebarFile: './sidebars/accessanalyzer/2601.js', }, { version: '12.0', From d8c916eac9613ffe20bbad56457b2fc72223a45d Mon Sep 17 00:00:00 2001 From: carlos-mejia_nwx Date: Wed, 8 Apr 2026 00:08:33 -0400 Subject: [PATCH 09/62] =?UTF-8?q?AA26:=20Remove=20Unity,=20Celerra,=20and?= =?UTF-8?q?=20VNX=20connector=20pages=20=E2=80=94=20not=20supported=20at?= =?UTF-8?q?=20GA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- .../2601/connectors/file-servers/celerra.md | 9 --------- .../accessanalyzer/2601/connectors/file-servers/unity.md | 9 --------- docs/accessanalyzer/2601/connectors/file-servers/vnx.md | 9 --------- 3 files changed, 27 deletions(-) delete mode 100644 docs/accessanalyzer/2601/connectors/file-servers/celerra.md delete mode 100644 docs/accessanalyzer/2601/connectors/file-servers/unity.md delete mode 100644 docs/accessanalyzer/2601/connectors/file-servers/vnx.md diff --git a/docs/accessanalyzer/2601/connectors/file-servers/celerra.md b/docs/accessanalyzer/2601/connectors/file-servers/celerra.md deleted file mode 100644 index e562473a05..0000000000 --- a/docs/accessanalyzer/2601/connectors/file-servers/celerra.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Celerra" -description: "Connector requirements for Dell Celerra file servers" -sidebar_position: 30 ---- - -# Celerra - -*Content coming soon.* diff --git a/docs/accessanalyzer/2601/connectors/file-servers/unity.md b/docs/accessanalyzer/2601/connectors/file-servers/unity.md deleted file mode 100644 index 55cc8ba73a..0000000000 --- a/docs/accessanalyzer/2601/connectors/file-servers/unity.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Unity" -description: "Connector requirements for Dell Unity file servers" -sidebar_position: 20 ---- - -# Unity - -*Content coming soon.* diff --git a/docs/accessanalyzer/2601/connectors/file-servers/vnx.md b/docs/accessanalyzer/2601/connectors/file-servers/vnx.md deleted file mode 100644 index cbaba1af7a..0000000000 --- a/docs/accessanalyzer/2601/connectors/file-servers/vnx.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "VNX" -description: "Connector requirements for Dell VNX file servers" -sidebar_position: 40 ---- - -# VNX - -*Content coming soon.* From e202efce83cd318bb5bda3f8b526970047230664 Mon Sep 17 00:00:00 2001 From: Farrah Gamboa Date: Thu, 9 Apr 2026 14:06:44 -0700 Subject: [PATCH 10/62] AA26: Add quick start guides, schema references, reports pages, and overview MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add full quick start guides for Active Directory, File Servers, Entra ID, and SharePoint Online — each with a scanning overview, scanning options, set-up walkthrough, schema reference (where applicable), and reports page - Add product overview and architecture overview with Mermaid diagram - Restructure configurations: flatten configuration-node hierarchy, nest Scanners under Source Groups, add service accounts subsection - Add SharePoint Online connector overview page - Remove replaced stubs: activity-data, activity-monitor-integration, old getting-started placeholders, top-level scanners section - Update inbound links to reflect new scanner path under source-groups Generated with AI Co-Authored-By: Claude Code --- .../2601/configurations/_category_.json | 2 +- .../application-settings.md | 0 .../sensitive-data/_category_.json | 6 - .../sensitive-data/mip-labeling.md | 9 - .../sensitive-data/overview.md | 9 - .../configuration-node/service-accounts.md | 9 - .../{configuration-node => }/logs.md | 0 .../{configuration-node => }/notifications.md | 0 .../2601/configurations/sensitive-data.md | 11 + .../service-accounts/_category_.json | 6 + .../service-accounts/entra-id.md | 19 ++ .../service-accounts/overview.md | 29 ++ .../service-accounts/sharepoint-online.md | 24 ++ .../service-accounts/username-password.md | 29 ++ .../_category_.json | 2 +- .../scan-executions.md | 2 +- .../source-groups}/scanners/_category_.json | 0 .../source-groups}/scanners/best-practices.md | 0 .../source-groups}/scanners/overview.md | 0 .../scans.md | 2 +- .../source-groups.md | 2 +- .../{configuration-node => }/users.md | 0 .../2601/connectors/activedirectory.md | 14 + .../2601/connectors/file-servers/cifs.md | 2 +- .../sharepoint-online/_category_.json | 6 +- .../connectors/sharepoint-online/overview.md | 37 +++ .../active-directory-sync/active-directory.md | 9 - .../_category_.json | 2 +- .../active-directory/active-directory.md | 32 ++ .../active-directory/reports.md | 15 + .../active-directory/scanning-options.md | 11 + .../active-directory/schema-reference.md | 273 ++++++++++++++++++ .../active-directory/set-up-source-group.md | 57 ++++ .../activity-data/_category_.json | 6 - .../activity-data/file-server-activity.md | 9 - .../_category_.json | 6 - .../activity-monitor-integration/overview.md | 9 - .../gettingstarted/entra-id-sync/entra-id.md | 9 - .../_category_.json | 2 +- .../2601/gettingstarted/entra-id/entra-id.md | 34 +++ .../entra-id/scanning-options.md | 11 + .../entra-id/set-up-source-group.md | 45 +++ .../file-server-scans/file-server.md | 9 - .../_category_.json | 2 +- .../file-servers/file-servers.md | 31 ++ .../gettingstarted/file-servers/reports.md | 31 ++ .../file-servers/scanning-options.md | 28 ++ .../file-servers/schema-reference.md | 201 +++++++++++++ .../file-servers/set-up-source-group.md | 62 ++++ .../gettingstarted/first-service-account.md | 9 - .../sharepoint-online.md | 9 - .../_category_.json | 2 +- .../sharepoint-online/reports.md | 17 ++ .../sharepoint-online/scanning-options.md | 17 ++ .../sharepoint-online/schema-reference.md | 166 +++++++++++ .../sharepoint-online/set-up-source-group.md | 49 ++++ .../sharepoint-online/sharepoint-online.md | 33 +++ .../gettingstarted/source-group-wizard.md | 9 - docs/accessanalyzer/2601/overview/overview.md | 100 +++++++ kb_allowlist.json | 4 +- 60 files changed, 1399 insertions(+), 130 deletions(-) rename docs/accessanalyzer/2601/configurations/{configuration-node => }/application-settings.md (100%) delete mode 100644 docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/_category_.json delete mode 100644 docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/mip-labeling.md delete mode 100644 docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/overview.md delete mode 100644 docs/accessanalyzer/2601/configurations/configuration-node/service-accounts.md rename docs/accessanalyzer/2601/configurations/{configuration-node => }/logs.md (100%) rename docs/accessanalyzer/2601/configurations/{configuration-node => }/notifications.md (100%) create mode 100644 docs/accessanalyzer/2601/configurations/sensitive-data.md create mode 100644 docs/accessanalyzer/2601/configurations/service-accounts/_category_.json create mode 100644 docs/accessanalyzer/2601/configurations/service-accounts/entra-id.md create mode 100644 docs/accessanalyzer/2601/configurations/service-accounts/overview.md create mode 100644 docs/accessanalyzer/2601/configurations/service-accounts/sharepoint-online.md create mode 100644 docs/accessanalyzer/2601/configurations/service-accounts/username-password.md rename docs/accessanalyzer/2601/configurations/{configuration-node => source-groups}/_category_.json (69%) rename docs/accessanalyzer/2601/configurations/{configuration-node => source-groups}/scan-executions.md (87%) rename docs/accessanalyzer/2601/{ => configurations/source-groups}/scanners/_category_.json (100%) rename docs/accessanalyzer/2601/{ => configurations/source-groups}/scanners/best-practices.md (100%) rename docs/accessanalyzer/2601/{ => configurations/source-groups}/scanners/overview.md (100%) rename docs/accessanalyzer/2601/configurations/{configuration-node => source-groups}/scans.md (84%) rename docs/accessanalyzer/2601/configurations/{configuration-node => source-groups}/source-groups.md (86%) rename docs/accessanalyzer/2601/configurations/{configuration-node => }/users.md (100%) create mode 100644 docs/accessanalyzer/2601/connectors/sharepoint-online/overview.md delete mode 100644 docs/accessanalyzer/2601/gettingstarted/active-directory-sync/active-directory.md rename docs/accessanalyzer/2601/gettingstarted/{active-directory-sync => active-directory}/_category_.json (61%) create mode 100644 docs/accessanalyzer/2601/gettingstarted/active-directory/active-directory.md create mode 100644 docs/accessanalyzer/2601/gettingstarted/active-directory/reports.md create mode 100644 docs/accessanalyzer/2601/gettingstarted/active-directory/scanning-options.md create mode 100644 docs/accessanalyzer/2601/gettingstarted/active-directory/schema-reference.md create mode 100644 docs/accessanalyzer/2601/gettingstarted/active-directory/set-up-source-group.md delete mode 100644 docs/accessanalyzer/2601/gettingstarted/activity-data/_category_.json delete mode 100644 docs/accessanalyzer/2601/gettingstarted/activity-data/file-server-activity.md delete mode 100644 docs/accessanalyzer/2601/gettingstarted/activity-monitor-integration/_category_.json delete mode 100644 docs/accessanalyzer/2601/gettingstarted/activity-monitor-integration/overview.md delete mode 100644 docs/accessanalyzer/2601/gettingstarted/entra-id-sync/entra-id.md rename docs/accessanalyzer/2601/gettingstarted/{entra-id-sync => entra-id}/_category_.json (67%) create mode 100644 docs/accessanalyzer/2601/gettingstarted/entra-id/entra-id.md create mode 100644 docs/accessanalyzer/2601/gettingstarted/entra-id/scanning-options.md create mode 100644 docs/accessanalyzer/2601/gettingstarted/entra-id/set-up-source-group.md delete mode 100644 docs/accessanalyzer/2601/gettingstarted/file-server-scans/file-server.md rename docs/accessanalyzer/2601/gettingstarted/{file-server-scans => file-servers}/_category_.json (64%) create mode 100644 docs/accessanalyzer/2601/gettingstarted/file-servers/file-servers.md create mode 100644 docs/accessanalyzer/2601/gettingstarted/file-servers/reports.md create mode 100644 docs/accessanalyzer/2601/gettingstarted/file-servers/scanning-options.md create mode 100644 docs/accessanalyzer/2601/gettingstarted/file-servers/schema-reference.md create mode 100644 docs/accessanalyzer/2601/gettingstarted/file-servers/set-up-source-group.md delete mode 100644 docs/accessanalyzer/2601/gettingstarted/first-service-account.md delete mode 100644 docs/accessanalyzer/2601/gettingstarted/sharepoint-online-scan/sharepoint-online.md rename docs/accessanalyzer/2601/gettingstarted/{sharepoint-online-scan => sharepoint-online}/_category_.json (61%) create mode 100644 docs/accessanalyzer/2601/gettingstarted/sharepoint-online/reports.md create mode 100644 docs/accessanalyzer/2601/gettingstarted/sharepoint-online/scanning-options.md create mode 100644 docs/accessanalyzer/2601/gettingstarted/sharepoint-online/schema-reference.md create mode 100644 docs/accessanalyzer/2601/gettingstarted/sharepoint-online/set-up-source-group.md create mode 100644 docs/accessanalyzer/2601/gettingstarted/sharepoint-online/sharepoint-online.md delete mode 100644 docs/accessanalyzer/2601/gettingstarted/source-group-wizard.md create mode 100644 docs/accessanalyzer/2601/overview/overview.md diff --git a/docs/accessanalyzer/2601/configurations/_category_.json b/docs/accessanalyzer/2601/configurations/_category_.json index 76daee8c8e..e493e2c253 100644 --- a/docs/accessanalyzer/2601/configurations/_category_.json +++ b/docs/accessanalyzer/2601/configurations/_category_.json @@ -1,6 +1,6 @@ { "label": "Configuration", - "position": 30, + "position": 16, "collapsed": true, "collapsible": true } diff --git a/docs/accessanalyzer/2601/configurations/configuration-node/application-settings.md b/docs/accessanalyzer/2601/configurations/application-settings.md similarity index 100% rename from docs/accessanalyzer/2601/configurations/configuration-node/application-settings.md rename to docs/accessanalyzer/2601/configurations/application-settings.md diff --git a/docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/_category_.json b/docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/_category_.json deleted file mode 100644 index 7965ccfb43..0000000000 --- a/docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Sensitive Data", - "position": 60, - "collapsed": true, - "collapsible": true -} diff --git a/docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/mip-labeling.md b/docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/mip-labeling.md deleted file mode 100644 index 32bed90184..0000000000 --- a/docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/mip-labeling.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "MIP Labeling" -description: "Microsoft Information Protection labeling and workflow configuration" -sidebar_position: 10 ---- - -# MIP Labeling - -*Content coming soon.* diff --git a/docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/overview.md b/docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/overview.md deleted file mode 100644 index b1535ed51f..0000000000 --- a/docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/overview.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Sensitive Data" -description: "Managing sensitive data settings in the Configuration node" -sidebar_position: 5 ---- - -# Sensitive Data - -*Content coming soon.* diff --git a/docs/accessanalyzer/2601/configurations/configuration-node/service-accounts.md b/docs/accessanalyzer/2601/configurations/configuration-node/service-accounts.md deleted file mode 100644 index 956d4289c2..0000000000 --- a/docs/accessanalyzer/2601/configurations/configuration-node/service-accounts.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Service Accounts" -description: "Managing service accounts in the Configuration node" -sidebar_position: 10 ---- - -# Service Accounts - -*Content coming soon.* diff --git a/docs/accessanalyzer/2601/configurations/configuration-node/logs.md b/docs/accessanalyzer/2601/configurations/logs.md similarity index 100% rename from docs/accessanalyzer/2601/configurations/configuration-node/logs.md rename to docs/accessanalyzer/2601/configurations/logs.md diff --git a/docs/accessanalyzer/2601/configurations/configuration-node/notifications.md b/docs/accessanalyzer/2601/configurations/notifications.md similarity index 100% rename from docs/accessanalyzer/2601/configurations/configuration-node/notifications.md rename to docs/accessanalyzer/2601/configurations/notifications.md diff --git a/docs/accessanalyzer/2601/configurations/sensitive-data.md b/docs/accessanalyzer/2601/configurations/sensitive-data.md new file mode 100644 index 0000000000..cb72b8ca1f --- /dev/null +++ b/docs/accessanalyzer/2601/configurations/sensitive-data.md @@ -0,0 +1,11 @@ +--- +title: "Sensitive Data" +description: "Configure sensitive data scanning settings in Access Analyzer" +sidebar_position: 30 +--- + +# Sensitive Data + +Sensitive data configuration controls how Access Analyzer identifies and classifies sensitive content during scans. Settings apply globally across all source groups that include sensitive data scanning. + +Configuration options include classification criteria, file type filters, and scanning depth. These settings determine what qualifies as sensitive data in scan results and how it is reported in the dashboards. diff --git a/docs/accessanalyzer/2601/configurations/service-accounts/_category_.json b/docs/accessanalyzer/2601/configurations/service-accounts/_category_.json new file mode 100644 index 0000000000..25ffc0442b --- /dev/null +++ b/docs/accessanalyzer/2601/configurations/service-accounts/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Service Accounts", + "position": 10, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/2601/configurations/service-accounts/entra-id.md b/docs/accessanalyzer/2601/configurations/service-accounts/entra-id.md new file mode 100644 index 0000000000..e62de9a69e --- /dev/null +++ b/docs/accessanalyzer/2601/configurations/service-accounts/entra-id.md @@ -0,0 +1,19 @@ +--- +title: "Entra ID Service Account" +description: "Client ID and secret service accounts for Entra ID source groups" +sidebar_position: 3 +--- + +# Entra ID Service Account + +Entra ID source groups use the Client ID and Secret credential type to authenticate with Microsoft Entra ID via the Microsoft Graph API. This requires a registered application in your Entra ID tenant with the appropriate API permissions granted. + +## Fields + +| Field | Description | +| --- | --- | +| **Name** | A display name that identifies this service account in Access Analyzer. | +| **Client ID** | The Application (client) ID of your registered Entra ID application. Must be a valid UUID (for example, `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`). Find this in the Azure portal under **Azure Active Directory** > **App registrations** > your app > **Overview**. | +| **Client Secret** | A client secret generated for the registered application. Create one in the Azure portal under your app's **Certificates & secrets**. | + +For steps to register the application and grant the required API permissions, see [Entra ID Requirements](../../connectors/entra-id/overview.md). diff --git a/docs/accessanalyzer/2601/configurations/service-accounts/overview.md b/docs/accessanalyzer/2601/configurations/service-accounts/overview.md new file mode 100644 index 0000000000..d3d151b21e --- /dev/null +++ b/docs/accessanalyzer/2601/configurations/service-accounts/overview.md @@ -0,0 +1,29 @@ +--- +title: "Overview" +description: "How service accounts work in Access Analyzer and which credential type each data source requires" +sidebar_position: 1 +--- + +# Overview + +Service accounts store the credentials Access Analyzer uses to authenticate against data sources during scans. Each data source connector requires a specific credential type, and the source group wizard automatically selects the correct type when you set up a new source group. + +You can create a service account in two ways: + +- **Inline during source group setup** — Click **+** next to the **Service Account** field in the source group wizard. The wizard locks the credential type to match the data source being configured. +- **In advance from Configuration** — Navigate to **Configuration** > **Service Accounts** and click **Add**. Select the credential type that matches your intended data source. + +## Credential Types by Data Source + +| Data Source | Credential Type | +| --- | --- | +| Active Directory | Username and Password | +| File Server | Username and Password | +| Entra ID | Client ID and Secret | +| SharePoint Online | Client ID and Certificate | + +## Editing Service Accounts + +Credential fields — passwords and client secrets — are never pre-populated when you edit an existing service account. You must re-enter them each time you save changes. + +Updating the service account on an existing source group replaces the credentials used for all future scans in that source group. Ensure the replacement account has the required permissions before saving. diff --git a/docs/accessanalyzer/2601/configurations/service-accounts/sharepoint-online.md b/docs/accessanalyzer/2601/configurations/service-accounts/sharepoint-online.md new file mode 100644 index 0000000000..d9db342fe0 --- /dev/null +++ b/docs/accessanalyzer/2601/configurations/service-accounts/sharepoint-online.md @@ -0,0 +1,24 @@ +--- +title: "SharePoint Online Service Account" +description: "Client ID and certificate service accounts for SharePoint Online source groups" +sidebar_position: 4 +--- + +# SharePoint Online Service Account + +SharePoint Online source groups use the Client ID and Certificate credential type to authenticate with SharePoint Online using certificate-based authentication. This requires a registered application in your Entra ID tenant. The certificate is generated by the source group wizard — you don't create or upload it here. + +## Fields + +| Field | Description | +| --- | --- | +| **Name** | A display name that identifies this service account in Access Analyzer. | +| **Client ID** | The Application (client) ID of your registered Entra ID application. Must be a valid UUID (for example, `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`). Find this in the Azure portal under **Azure Active Directory** > **App registrations** > your app > **Overview**. | + +## Certificate + +The certificate is not entered manually. When you set up a SharePoint Online source group, the wizard includes a **Generate and Download Certificate** step that creates the certificate and downloads it to your machine. You then upload the certificate to your registered Entra ID application in the Azure portal before testing the connection. + +If you update the service account on an existing source group, the new account's certificate must be uploaded to the registered app before saving. + +For steps to register the application and upload the certificate, see [SharePoint Online Connector Requirements](../../connectors/sharepoint-online/overview.md). diff --git a/docs/accessanalyzer/2601/configurations/service-accounts/username-password.md b/docs/accessanalyzer/2601/configurations/service-accounts/username-password.md new file mode 100644 index 0000000000..aecba5470d --- /dev/null +++ b/docs/accessanalyzer/2601/configurations/service-accounts/username-password.md @@ -0,0 +1,29 @@ +--- +title: "Username and Password" +description: "Username and password service accounts for Active Directory and file server source groups" +sidebar_position: 2 +--- + +# Username and Password + +The Username and Password credential type is used by Active Directory and file server source groups. Both require a domain account whose credentials Access Analyzer uses to connect and authenticate during scans. + +## Fields + +| Field | Description | +| --- | --- | +| **Name** | A display name that identifies this service account in Access Analyzer. | +| **Username** | The domain user account in `DOMAIN\username` format. | +| **Password** | The password for the domain account. | + +## Active Directory + +Active Directory source groups use the service account to connect to domain controllers over LDAP or LDAPS and read directory objects. The account must have Read access to the Active Directory directory tree. + +For full permission requirements, see [Active Directory Connector Requirements](../../connectors/activedirectory.md). + +## File Server + +File server source groups use the service account to connect to Windows file servers over SMB and enumerate shares, permissions, and file contents. The account must be a member of the same domain as the target file servers. The specific permissions required depend on the scan types you enable — access scanning and sensitive data scanning have different requirements. + +For full permission requirements, see [CIFS / SMB File Share](../../connectors/file-servers/cifs.md). diff --git a/docs/accessanalyzer/2601/configurations/configuration-node/_category_.json b/docs/accessanalyzer/2601/configurations/source-groups/_category_.json similarity index 69% rename from docs/accessanalyzer/2601/configurations/configuration-node/_category_.json rename to docs/accessanalyzer/2601/configurations/source-groups/_category_.json index 70b787ca97..e3bbafe95d 100644 --- a/docs/accessanalyzer/2601/configurations/configuration-node/_category_.json +++ b/docs/accessanalyzer/2601/configurations/source-groups/_category_.json @@ -1,5 +1,5 @@ { - "label": "Settings", + "label": "Source Groups", "position": 20, "collapsed": true, "collapsible": true diff --git a/docs/accessanalyzer/2601/configurations/configuration-node/scan-executions.md b/docs/accessanalyzer/2601/configurations/source-groups/scan-executions.md similarity index 87% rename from docs/accessanalyzer/2601/configurations/configuration-node/scan-executions.md rename to docs/accessanalyzer/2601/configurations/source-groups/scan-executions.md index d2f01e283b..06fdfae6a1 100644 --- a/docs/accessanalyzer/2601/configurations/configuration-node/scan-executions.md +++ b/docs/accessanalyzer/2601/configurations/source-groups/scan-executions.md @@ -1,7 +1,7 @@ --- title: "Scan Executions" description: "Viewing scan execution history in the Configuration node" -sidebar_position: 40 +sidebar_position: 3 --- # Scan Executions diff --git a/docs/accessanalyzer/2601/scanners/_category_.json b/docs/accessanalyzer/2601/configurations/source-groups/scanners/_category_.json similarity index 100% rename from docs/accessanalyzer/2601/scanners/_category_.json rename to docs/accessanalyzer/2601/configurations/source-groups/scanners/_category_.json diff --git a/docs/accessanalyzer/2601/scanners/best-practices.md b/docs/accessanalyzer/2601/configurations/source-groups/scanners/best-practices.md similarity index 100% rename from docs/accessanalyzer/2601/scanners/best-practices.md rename to docs/accessanalyzer/2601/configurations/source-groups/scanners/best-practices.md diff --git a/docs/accessanalyzer/2601/scanners/overview.md b/docs/accessanalyzer/2601/configurations/source-groups/scanners/overview.md similarity index 100% rename from docs/accessanalyzer/2601/scanners/overview.md rename to docs/accessanalyzer/2601/configurations/source-groups/scanners/overview.md diff --git a/docs/accessanalyzer/2601/configurations/configuration-node/scans.md b/docs/accessanalyzer/2601/configurations/source-groups/scans.md similarity index 84% rename from docs/accessanalyzer/2601/configurations/configuration-node/scans.md rename to docs/accessanalyzer/2601/configurations/source-groups/scans.md index 0f21da4b92..cbd6f26304 100644 --- a/docs/accessanalyzer/2601/configurations/configuration-node/scans.md +++ b/docs/accessanalyzer/2601/configurations/source-groups/scans.md @@ -1,7 +1,7 @@ --- title: "Scans" description: "Managing scans in the Configuration node" -sidebar_position: 30 +sidebar_position: 2 --- # Scans diff --git a/docs/accessanalyzer/2601/configurations/configuration-node/source-groups.md b/docs/accessanalyzer/2601/configurations/source-groups/source-groups.md similarity index 86% rename from docs/accessanalyzer/2601/configurations/configuration-node/source-groups.md rename to docs/accessanalyzer/2601/configurations/source-groups/source-groups.md index 0eab251842..1ee2b78421 100644 --- a/docs/accessanalyzer/2601/configurations/configuration-node/source-groups.md +++ b/docs/accessanalyzer/2601/configurations/source-groups/source-groups.md @@ -1,7 +1,7 @@ --- title: "Source Groups" description: "Managing source groups in the Configuration node" -sidebar_position: 20 +sidebar_position: 1 --- # Source Groups diff --git a/docs/accessanalyzer/2601/configurations/configuration-node/users.md b/docs/accessanalyzer/2601/configurations/users.md similarity index 100% rename from docs/accessanalyzer/2601/configurations/configuration-node/users.md rename to docs/accessanalyzer/2601/configurations/users.md diff --git a/docs/accessanalyzer/2601/connectors/activedirectory.md b/docs/accessanalyzer/2601/connectors/activedirectory.md index 6a2949d4f2..916c73f9f5 100644 --- a/docs/accessanalyzer/2601/connectors/activedirectory.md +++ b/docs/accessanalyzer/2601/connectors/activedirectory.md @@ -28,6 +28,8 @@ The following must be installed on each domain controller to be scanned: Use Domain Administrator or Local Administrator privileges when running Access Analyzer against an Active Directory domain controller. ::: +A least privilege model can be configured based on your auditing needs. See the [Least Privilege Model](#least-privilege-model) section for additional information. + ## Port Requirements The following firewall ports are required for the Active Directory connector: @@ -35,5 +37,17 @@ The following firewall ports are required for the Active Directory connector: | Port | Protocol | Description | | --- | --- | --- | | 389 | TCP | LDAP | +| 636 | TCP | LDAPS | | 135–139 | TCP | RPC | | Randomly allocated high TCP ports | TCP | RPC dynamic ports | + +## Least Privilege Model + +The following minimum permissions must be configured at the domain level in Active Directory: + +- Read access to directory tree +- List Contents and Read Property on the Deleted Objects Container + +:::note +See the Microsoft [Searching for Deleted Objects](https://technet.microsoft.com/en-us/library/cc978013.aspx) article and the Microsoft [Dsacls](https://technet.microsoft.com/en-us/library/cc771151(v=ws.11).aspx) article for additional information. +::: diff --git a/docs/accessanalyzer/2601/connectors/file-servers/cifs.md b/docs/accessanalyzer/2601/connectors/file-servers/cifs.md index e4ceab825e..dcf557fddc 100644 --- a/docs/accessanalyzer/2601/connectors/file-servers/cifs.md +++ b/docs/accessanalyzer/2601/connectors/file-servers/cifs.md @@ -8,7 +8,7 @@ sidebar_position: 10 Access Analyzer scans Windows file servers to enumerate files, folders, access permissions, and sensitive data. -Scanning can be performed directly from the Access Analyzer service (local mode) or via Scanners — Kubernetes-deployed containers for distributed scanning of remote environments. See the [Utilizing Scanners](../../scanners/overview.md) section for details on Scanner architecture. +Scanning can be performed directly from the Access Analyzer service (local mode) or via Scanners — Kubernetes-deployed containers for distributed scanning of remote environments. See the [Utilizing Scanners](../../configurations/source-groups/scanners/overview.md) section for details on Scanner architecture. ## Permissions diff --git a/docs/accessanalyzer/2601/connectors/sharepoint-online/_category_.json b/docs/accessanalyzer/2601/connectors/sharepoint-online/_category_.json index a8d05dd13b..aebbe26706 100644 --- a/docs/accessanalyzer/2601/connectors/sharepoint-online/_category_.json +++ b/docs/accessanalyzer/2601/connectors/sharepoint-online/_category_.json @@ -2,5 +2,9 @@ "label": "SharePoint Online", "position": 50, "collapsed": true, - "collapsible": true + "collapsible": true, + "link": { + "type": "doc", + "id": "connectors/sharepoint-online/overview" + } } diff --git a/docs/accessanalyzer/2601/connectors/sharepoint-online/overview.md b/docs/accessanalyzer/2601/connectors/sharepoint-online/overview.md new file mode 100644 index 0000000000..66e6768af4 --- /dev/null +++ b/docs/accessanalyzer/2601/connectors/sharepoint-online/overview.md @@ -0,0 +1,37 @@ +--- +title: "SharePoint Online" +description: "Requirements for connecting Access Analyzer to SharePoint Online" +sidebar_position: 1 +--- + +# SharePoint Online + +Access Analyzer connects to SharePoint Online using modern authentication, including support for multi-factor authentication (MFA). It authenticates through a pre-configured Microsoft Entra ID application and accesses SharePoint Online through Microsoft Graph and other modern APIs. + +Before adding SharePoint Online as a data source, you must register a dedicated Microsoft Entra ID application and grant it the required permissions. + +## Scan Types + +Access Analyzer supports two scan types for SharePoint Online: + +| Scan Type | Description | Authentication | +| --- | --- | --- | +| **Access scan** | Enumerates files, folders, and permissions to identify who has access to what | Client secret | +| **State-in-time scan** | Captures a permissions snapshot at a point in time for compliance and risk reporting | Certificate | + +Both scan types use the same registered Entra ID application. The certificate is an additional credential required only for state-in-time scans. + +## Before You Begin + +You need the following before adding SharePoint Online as a data source: + +- A user account with the **Global Administrator**, **Application Administrator**, or **Cloud Application Administrator** role in Microsoft Entra ID, to register an application and grant admin consent for permissions +- A registered Microsoft Entra ID application with the required API permissions — see [App Permissions in Entra](azure-permissions.md) +- A client secret generated for the registered application — see [Certificate Configuration](tenant-certificate-config.md) +- A certificate uploaded to the registered application (state-in-time scans only) — see [Certificate Configuration](tenant-certificate-config.md) + +When configuring the SharePoint Online source in Access Analyzer, you will need the following values from your registered application: + +- **Application (client) ID** +- **Directory (tenant) ID** +- **Client secret value** diff --git a/docs/accessanalyzer/2601/gettingstarted/active-directory-sync/active-directory.md b/docs/accessanalyzer/2601/gettingstarted/active-directory-sync/active-directory.md deleted file mode 100644 index f723d5e4a8..0000000000 --- a/docs/accessanalyzer/2601/gettingstarted/active-directory-sync/active-directory.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Active Directory Source Group" -description: "Making changes to an Active Directory source group wizard workflow" -sidebar_position: 10 ---- - -# Active Directory Source Group - -*Content coming soon.* diff --git a/docs/accessanalyzer/2601/gettingstarted/active-directory-sync/_category_.json b/docs/accessanalyzer/2601/gettingstarted/active-directory/_category_.json similarity index 61% rename from docs/accessanalyzer/2601/gettingstarted/active-directory-sync/_category_.json rename to docs/accessanalyzer/2601/gettingstarted/active-directory/_category_.json index fc2c06370c..78b3bd0452 100644 --- a/docs/accessanalyzer/2601/gettingstarted/active-directory-sync/_category_.json +++ b/docs/accessanalyzer/2601/gettingstarted/active-directory/_category_.json @@ -1,5 +1,5 @@ { - "label": "Scanning Active Directory", + "label": "Active Directory", "position": 20, "collapsed": true, "collapsible": true diff --git a/docs/accessanalyzer/2601/gettingstarted/active-directory/active-directory.md b/docs/accessanalyzer/2601/gettingstarted/active-directory/active-directory.md new file mode 100644 index 0000000000..dba78e02cd --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/active-directory/active-directory.md @@ -0,0 +1,32 @@ +--- +title: "Active Directory Scanning Overview" +description: "Overview of Active Directory scanning capabilities and prerequisites in Access Analyzer" +sidebar_position: 1 +--- + +# Active Directory Scanning Overview + +Access Analyzer scans Active Directory to inventory users, groups, group memberships, and organizational units across one or more domains. It detects security risks including stale accounts, privileged account exposure, excessive group nesting, and accounts with unusual delegation settings. Findings surface in the Active Directory Dashboard, giving security teams a clear picture of their identity posture and the data they need to prioritize remediation. + +## Prerequisites + +Before setting up an Active Directory source group, confirm that your environment meets the requirements below. The source group wizard connects to your domain controllers over LDAP or LDAPS, so the Access Analyzer server must be able to reach them on the network and a domain service account must be available with the appropriate read permissions. + +### Service Account + +Access Analyzer uses a domain service account to authenticate against your Active Directory domain controllers and read directory objects. The account must be a member of the domain you're scanning and have Read access to the directory tree. + +See [Username and Password](../../configurations/service-accounts/username-password.md) to create the service account and [Active Directory Connector Requirements](../../connectors/activedirectory.md) for the full list of required permissions. + +### Network Requirements + +| Protocol | Port | Destination | +| --- | --- | --- | +| LDAP | 389 | Domain controllers in the source group | +| LDAPS | 636 | Domain controllers in the source group (if using SSL) | + +### Before You Begin + +- The fully qualified domain name (FQDN) of each domain controller you plan to add. IP addresses are not supported — DIGEST-MD5 authentication requires a resolvable hostname and will fail if an IP address is provided. +- A Username and Password service account created in Access Analyzer with Read access to the domain. +- Network connectivity from the Access Analyzer server to port 389 or 636 on each domain controller confirmed. diff --git a/docs/accessanalyzer/2601/gettingstarted/active-directory/reports.md b/docs/accessanalyzer/2601/gettingstarted/active-directory/reports.md new file mode 100644 index 0000000000..51d8be3d72 --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/active-directory/reports.md @@ -0,0 +1,15 @@ +--- +title: "Reports" +description: "Pre-built dashboard available for Active Directory source groups in Access Analyzer" +sidebar_position: 50 +--- + +# Reports + +After the first Active Directory scan completes, the Active Directory Dashboard becomes available under the Dashboards section. The dashboard surfaces user and group inventory data alongside detected security risks, letting you answer questions such as how many privileged accounts exist in a domain, which users and groups carry the most risk findings, and what the overall distribution of risk severity looks like across your Active Directory environment. + +## Available reports + +| Location | Report | Description | +|----------|--------|-------------| +| Active Directory | Active Directory Dashboard | An overview of Active Directory scan results for one or more domains. Shows inventory counts for users, groups, and group memberships alongside security risk data, including risk breakdowns by type and severity and a ranked list of the objects with the highest number of associated risks. Filter by domain to focus on a specific part of your environment. | diff --git a/docs/accessanalyzer/2601/gettingstarted/active-directory/scanning-options.md b/docs/accessanalyzer/2601/gettingstarted/active-directory/scanning-options.md new file mode 100644 index 0000000000..f940fdae3c --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/active-directory/scanning-options.md @@ -0,0 +1,11 @@ +--- +title: "Available Scanning Options" +description: "Available scan types for Active Directory source groups" +sidebar_position: 2 +--- + +# Available Scanning Options + +| Scan Option | Description | Available Configurations | +| --- | --- | --- | +| **Active Directory Inventory** | Scans users, groups, and group memberships from all domain controllers in the source group. The first scan runs in full; subsequent scans run differentially, collecting only changes since the last run. | None | diff --git a/docs/accessanalyzer/2601/gettingstarted/active-directory/schema-reference.md b/docs/accessanalyzer/2601/gettingstarted/active-directory/schema-reference.md new file mode 100644 index 0000000000..28d9258a29 --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/active-directory/schema-reference.md @@ -0,0 +1,273 @@ +--- +title: "Active Directory Schema Reference" +sidebar_position: 40 +--- + +# Active Directory Schema Reference + +Access Analyzer stores Active Directory scan data in the `access_analyzer` ClickHouse database. The tables below are created when you set up an Active Directory source group and run a scan. Use this reference when querying scan data directly or integrating Access Analyzer data with external tools. + +:::note +All tables use the `ReplacingMergeTree` engine. Duplicate rows with the same primary key are deduplicated at merge time. Query the `_latest` views to return only the most recent version of each record. +::: + +## Metadata columns + +All tables include the following columns populated by Access Analyzer during each scan: + +| Column | Type | Description | +|--------|------|-------------| +| `scan_id` | `String` | Identifier of the source group that produced this record. | +| `scan_execution_id` | `String` | Identifier of the specific scan run. | +| `scanned_at` | `DateTime` | Timestamp when the record was written. | + +--- + +## Tables + +### active_directory_user + +Stores one row per user object discovered in an Active Directory scan. + +**Primary key:** `object_guid` + +#### Core identity fields + +| Column | Type | Description | +|--------|------|-------------| +| `object_guid` | `UUID` | Globally unique identifier for the user object. | +| `object_sid` | `String` | Security identifier (SID) of the user. | +| `distinguished_name` | `String` | Full distinguished name (DN) of the user in the directory. | +| `canonical_name` | `Nullable(String)` | Optional. Canonical form of the distinguished name. | +| `sam_account_name` | `String` | Pre-Windows 2000 logon name (sAMAccountName). | +| `user_principal_name` | `Nullable(String)` | Optional. User principal name (UPN) in `user@domain` format. | +| `display_name` | `Nullable(String)` | Optional. Display name shown in directory listings. | +| `given_name` | `Nullable(String)` | Optional. First name of the user. | +| `surname` | `Nullable(String)` | Optional. Last name of the user. | +| `enabled` | `Bool` | Whether the user account is enabled. | +| `when_created` | `Nullable(DateTime)` | Optional. Timestamp when the account was created in the directory. | +| `when_changed` | `Nullable(DateTime)` | Optional. Timestamp of the most recent change to the account. | +| `description` | `Nullable(String)` | Optional. Description field set on the user object. | +| `admin_count` | `Nullable(Int32)` | Optional. Value of the `adminCount` attribute; non-zero values indicate the account is or was protected by AdminSDHolder. | +| `primary_group_id` | `Nullable(Int32)` | Optional. Relative identifier (RID) of the user's primary group. | +| `domain_name` | `Nullable(String)` | Optional. NetBIOS or DNS name of the domain. | +| `domain_canonical_name` | `Nullable(String)` | Optional. Canonical (DNS) name of the domain. | +| `cn` | `Nullable(String)` | Optional. Common name (CN) attribute of the user object. | + +#### Contact information + +| Column | Type | Description | +|--------|------|-------------| +| `mail` | `Nullable(String)` | Optional. Email address. | +| `telephone_number` | `Nullable(String)` | Optional. Office telephone number. | +| `mobile` | `Nullable(String)` | Optional. Mobile telephone number. | +| `office` | `Nullable(String)` | Optional. Office location. | +| `street_address` | `Nullable(String)` | Optional. Street address. | +| `city` | `Nullable(String)` | Optional. City. | +| `state` | `Nullable(String)` | Optional. State or province. | +| `postal_code` | `Nullable(String)` | Optional. Postal or ZIP code. | +| `country` | `Nullable(String)` | Optional. Country or region. | + +#### Organizational information + +| Column | Type | Description | +|--------|------|-------------| +| `job_title` | `Nullable(String)` | Optional. Job title. | +| `department` | `Nullable(String)` | Optional. Department. | +| `company` | `Nullable(String)` | Optional. Company or organization name. | +| `manager_dn` | `Nullable(String)` | Optional. Distinguished name of the user's manager. | +| `employee_id` | `Nullable(String)` | Optional. Employee identifier. | + +#### Security information + +| Column | Type | Description | +|--------|------|-------------| +| `user_account_control` | `Nullable(Int32)` | Optional. Bitmask value of the `userAccountControl` attribute controlling account behavior and flags. | +| `password_last_set` | `Nullable(DateTime)` | Optional. Timestamp when the password was last changed. | +| `password_never_expires` | `Nullable(Bool)` | Optional. Whether the password is set to never expire. | +| `account_expires` | `Nullable(String)` | Optional. Expiration date of the account, stored as a string representation of the directory value. | +| `logon_hours` | `Nullable(String)` | Optional. Bitmask string representing the hours during which the user is permitted to log on. | +| `logon_workstations` | `Array(String)` | List of workstations the user is permitted to log on to; empty array indicates no restriction. | +| `smartcard_required` | `Nullable(Bool)` | Optional. Whether the account requires a smart card to log on. | +| `mfa_enforced` | `Nullable(Bool)` | Optional. Whether multi-factor authentication is enforced for this account. | +| `is_deleted` | `Boolean` | Whether the user object has been soft-deleted. Rows where `is_deleted = 1` are excluded from the `active_directory_user_latest` view. | + +#### Activity information + +| Column | Type | Description | +|--------|------|-------------| +| `last_logon` | `Nullable(DateTime)` | Optional. Most recent logon timestamp from the domain controller that serviced the last logon. Not replicated across domain controllers. | +| `last_logon_timestamp` | `Nullable(DateTime)` | Optional. Replicated logon timestamp (`lastLogonTimestamp`); updated at intervals and may lag behind the actual last logon by up to 14 days. | +| `bad_pwd_count` | `Nullable(Int32)` | Optional. Number of consecutive failed logon attempts. | +| `bad_password_time` | `Nullable(DateTime)` | Optional. Timestamp of the last failed logon attempt. | +| `lockout_time` | `Nullable(DateTime)` | Optional. Timestamp when the account was locked out; `NULL` or zero indicates the account is not locked. | +| `last_logoff` | `Nullable(DateTime)` | Optional. Timestamp of the last logoff. | + +#### Delegation information + +| Column | Type | Description | +|--------|------|-------------| +| `ms_ds_allowed_to_act_on_behalf_of` | `Array(String)` | List of security descriptors for accounts permitted to delegate to this account using resource-based constrained delegation. | +| `ms_ds_allowed_to_delegate_to` | `Array(String)` | List of SPNs this account is permitted to delegate to using constrained delegation. | +| `ms_ds_supported_encryption_types` | `Nullable(Int32)` | Optional. Bitmask of Kerberos encryption types supported by this account. | +| `service_principal_name` | `Array(String)` | List of service principal names (SPNs) registered to this account. | +| `legacy_exchange_dn` | `Nullable(String)` | Optional. Legacy Exchange distinguished name, used for mail routing compatibility. | +| `ms_ds_user_account_control_computer` | `Nullable(Int32)` | Optional. Computer-specific `userAccountControl` flags stored on the user object in hybrid environments. | + +**Relations** + +| Related table | Join column | Description | +|---|---|---| +| `active_directory_group_membership` | `object_sid` via `foreign_sid` | Resolves groups that include this user when the user was added by SID from a foreign domain. | +| `active_directory_group_membership` | `distinguished_name` via `member_dn` | Resolves groups that include this user when the user was added by DN. | +| `active_directory_user_custom_attribute` | `object_guid` | Returns custom attribute values collected for this user. | +| `active_directory_effective_group_membership` | `object_guid` via `member_object_guid` | Returns all groups this user belongs to, including nested memberships. | + +--- + +### active_directory_group + +Stores one row per group object discovered in an Active Directory scan. + +**Primary key:** `object_guid` + +| Column | Type | Description | +|--------|------|-------------| +| `object_guid` | `UUID` | Globally unique identifier for the group object. | +| `object_sid` | `String` | Security identifier (SID) of the group. | +| `distinguished_name` | `String` | Full distinguished name (DN) of the group in the directory. | +| `sam_account_name` | `Nullable(String)` | Optional. Pre-Windows 2000 name of the group. | +| `name` | `Nullable(String)` | Optional. Display name of the group. | +| `group_scope` | `Nullable(String)` | Optional. Scope of the group: `DomainLocal`, `Global`, or `Universal`. | +| `group_type` | `Nullable(String)` | Optional. Type of the group: `Security` or `Distribution`. | +| `admin_count` | `Nullable(Int32)` | Optional. Value of the `adminCount` attribute; non-zero values indicate the group is or was protected by AdminSDHolder. | +| `primary_group_id` | `Nullable(Int32)` | Optional. Relative identifier (RID) associated with this group when it is used as a primary group. | +| `domain_name` | `Nullable(String)` | Optional. NetBIOS or DNS name of the domain. | +| `domain_canonical_name` | `Nullable(String)` | Optional. Canonical (DNS) name of the domain. | +| `cn` | `Nullable(String)` | Optional. Common name (CN) attribute of the group object. | +| `mail` | `Nullable(String)` | Optional. Email address associated with the group. | +| `is_deleted` | `Boolean` | Whether the group object has been soft-deleted. Rows where `is_deleted = 1` are excluded from the `active_directory_group_latest` view. | + +**Relations** + +| Related table | Join column | Description | +|---|---|---| +| `active_directory_group_membership` | `distinguished_name` via `group_dn` | Lists the direct members of this group. | +| `active_directory_effective_group_membership` | `object_guid` via `group_object_guid` | Lists all effective members of this group, including nested members. | + +--- + +### active_directory_group_membership + +Stores one row per direct membership relationship between a group and a member object (user or group). Nesting is not flattened in this table; use `active_directory_effective_group_membership` for flattened membership. + +**Primary key:** `(group_dn, member_dn)` + +| Column | Type | Description | +|--------|------|-------------| +| `group_dn` | `String` | Distinguished name (DN) of the group. | +| `member_dn` | `String` | Distinguished name (DN) of the member object. | +| `foreign_sid` | `Nullable(String)` | Optional. SID of the member when the member is from a foreign (trusted) domain and a DN is not available. | + +**Relations** + +| Related table | Join column | Description | +|---|---|---| +| `active_directory_group` | `group_dn` = `distinguished_name` | Resolves the group record for this membership row. | +| `active_directory_user` | `member_dn` = `distinguished_name` | Resolves the user record for this membership row when the member is a user. | +| `active_directory_group` | `member_dn` = `distinguished_name` | Resolves the group record for this membership row when the member is a nested group. | +| `active_directory_user` | `foreign_sid` = `object_sid` | Resolves a foreign-domain user by SID when `foreign_sid` is set. | +| `active_directory_group` | `foreign_sid` = `object_sid` | Resolves a foreign-domain group by SID when `foreign_sid` is set. | + +--- + +### active_directory_user_custom_attribute + +Stores custom Active Directory attribute values collected for user objects during a scan. Each row represents one attribute key-value pair for one user. An attribute with no value produces a row with `attr_value = NULL`. + +**Primary key:** `(object_guid, attr_name)` + +| Column | Type | Description | +|--------|------|-------------| +| `object_guid` | `UUID` | Globally unique identifier of the user object. Joins to `active_directory_user.object_guid`. | +| `attr_name` | `String` | LDAP attribute name, as configured in the source group settings. | +| `attr_value` | `Nullable(String)` | Optional. String representation of the attribute value. | + +**Relations** + +| Related table | Join column | Description | +|---|---|---| +| `active_directory_user` | `object_guid` | Returns the full user record for this custom attribute row. | + +--- + +### active_directory_effective_group_membership + +Stores the fully flattened, transitively resolved group membership graph. This table is populated by the `active_directory_effective_group_membership_mv` materialized view, which refreshes on a schedule after each scan. Each row represents one effective membership relationship at a given nesting depth. + +**Engine:** `MergeTree` (not `ReplacingMergeTree`). The table is rebuilt on each refresh rather than deduplicated by version. + +**Primary key:** `(group_object_guid, member_object_guid)` + +| Column | Type | Description | +|--------|------|-------------| +| `group_object_guid` | `UUID` | Globally unique identifier of the group. Joins to `active_directory_group.object_guid`. | +| `member_object_guid` | `UUID` | Globally unique identifier of the effective member (user or group). Joins to `active_directory_user.object_guid` or `active_directory_group.object_guid`. | +| `nesting_level` | `Int32` | Depth of the membership relationship. A value of `0` indicates direct membership; higher values indicate the number of intermediate groups. | + +**Relations** + +| Related table | Join column | Description | +|---|---|---| +| `active_directory_group` | `group_object_guid` = `object_guid` | Resolves the group name and attributes for this membership row. | +| `active_directory_user` | `member_object_guid` = `object_guid` | Resolves the user record when the effective member is a user. | +| `active_directory_group` | `member_object_guid` = `object_guid` | Resolves the group record when the effective member is a nested group. | + +--- + +## Views + +Access Analyzer creates views that simplify common queries. Use views in preference to querying base tables directly. + +### Deduplication views + +These views apply `FINAL` to the underlying `ReplacingMergeTree` tables to return only the most recent version of each record. Use these as the starting point for any query against Active Directory data. + +| View | Base table | Description | +|------|------------|-------------| +| `active_directory_user_latest` | `active_directory_user` | Returns the most recent version of each user record, deduplicated by `object_guid`, excluding soft-deleted users (`is_deleted = 1`). | +| `active_directory_group_latest` | `active_directory_group` | Returns the most recent version of each group record, deduplicated by `object_guid`, excluding soft-deleted groups (`is_deleted = 1`). | +| `active_directory_group_membership_latest` | `active_directory_group_membership` | Returns the most recent version of each group membership row, deduplicated by `(group_dn, member_dn)`. | +| `active_directory_user_custom_attribute_latest` | `active_directory_user_custom_attribute` | Returns the most recent version of each custom attribute row, deduplicated by `(object_guid, attr_name)`. | + +### Resolution views + +These views resolve raw membership data into UUID-keyed relationships. + +| View | Description | +|------|-------------| +| `active_directory_group_membership_resolved` | Joins `active_directory_group_membership_latest` to the user and group tables to produce a resolved membership graph keyed by `(group_object_guid, member_object_guid)`. Handles both same-domain members (matched by DN) and foreign-domain members (matched by SID). Excludes deleted objects. Used as the source for `active_directory_effective_group_membership_mv`. | + +### Risk views + +These views surface specific account and group hygiene conditions. Each view returns rows in a common shape: `risk_type`, `entity_id`, `entity_name`, `domain`, `detection_timestamp`, and `additional_context`. The `active_directory_risks_summary` view aggregates all risk views into a single result set enriched with catalog metadata. + +| View | Description | +|------|-------------| +| `active_directory_empty_groups` | Groups that have no effective members. | +| `active_directory_single_member_groups` | Groups that have exactly one effective member. | +| `active_directory_large_groups` | Groups that have more than 500 effective members. | +| `active_directory_duplicate_groups_mv` | Groups whose effective membership set is identical to that of at least one other group. | +| `active_directory_circular_nesting_mv` | Groups involved in circular nesting or with a nesting depth of 10 or more. | +| `active_directory_stale_users` | Enabled user accounts with no logon activity in the past 90 to 365 days. | +| `active_directory_very_stale_users` | Enabled user accounts with no logon activity for more than 365 days. | +| `active_directory_isolated_users` | Enabled user accounts that belong to no groups. | +| `active_directory_no_logon_users` | Enabled user accounts with no recorded logon timestamp. | +| `active_directory_password_never_expires` | Enabled user accounts configured with a non-expiring password. | +| `active_directory_password_not_required` | Enabled user accounts where the `PASSWD_NOTREQD` flag is set in `user_account_control`. | +| `active_directory_old_passwords` | Enabled user accounts whose password has not changed in more than 90 days. | +| `active_directory_dc_logon_rights` | Enabled users who are effective members of privileged groups that grant domain controller logon rights (for example, Domain Admins, Enterprise Admins). | +| `active_directory_risks_summary_mv` | Union of all individual risk views. Returns one row per detected risk. | +| `active_directory_risks_summary` | Enriches `active_directory_risks_summary_mv` with risk level, category, and description from the `active_directory_risk_catalog` reference table. Use this view to query all risks with their human-readable metadata. | +| `active_directory_risks_by_domain` | Aggregates risk counts by domain and risk type, sourced from `active_directory_risks_summary_mv`. | +| `active_directory_group_member_counts` | Returns the total effective member count for each group. Intermediate view used by the group risk views. | diff --git a/docs/accessanalyzer/2601/gettingstarted/active-directory/set-up-source-group.md b/docs/accessanalyzer/2601/gettingstarted/active-directory/set-up-source-group.md new file mode 100644 index 0000000000..571b505731 --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/active-directory/set-up-source-group.md @@ -0,0 +1,57 @@ +--- +title: "Set Up Active Directory Source Group" +description: "Configure an Active Directory source group in Access Analyzer" +sidebar_position: 3 +--- + +# Active Directory Source Group + +**Step 1 –** Navigate to **Configuration** > **Source Groups** and click **Add Source**. The source group wizard opens. + +**Step 2 –** Select **Active Directory** and click **Next**. + +**Step 3 –** Enter a **Source Group Name**. + +**Step 4 –** Select a service account from the **Service Account** dropdown, or click **+** to create one inline. Service accounts store the credentials Access Analyzer uses to connect to your domain controllers. See [Service Accounts](../../configurations/service-accounts/overview.md) for details. + +**Step 5 –** Click **Add** under **Domain Controllers**, then select **Add Manually**. + +**Step 6 –** Enter the following for each domain controller: + +- **Server Name / IP** — The FQDN of the domain controller. To add multiple domain controllers, separate entries with a comma or press **Enter** after each one. +- **Domain** — The DNS domain name (for example, `corp.example.com`). Applied to all entries above. +- **Port** — The LDAP port. Default is `389`. Use `636` for LDAPS. + +**Step 7 –** Click **Add domain controller**, then click **Done**. Repeat Steps 5–7 for each additional domain. + +**Step 8 –** If your domain controllers use self-signed certificates on port 636, select **Ignore SSL errors**. + +**Step 9 –** Click **Test Connection** to verify connectivity. Each domain controller displays a **Connected** or **Failed** status. Resolve any failures before proceeding. + +**Step 10 –** Click **Next**. + +**Step 11 –** Under **Scanner Location**, select **System scanner** to run scans from the Access Analyzer service, or select **Custom scanner** to use a deployed scanner. See [Scanners](../../configurations/source-groups/scanners/overview.md) for details. + +**Step 12 –** Under **Scan Schedule**, select when to run the scan: + +- **Now** — Starts the scan immediately after setup completes. +- **At** — Runs the scan once at a specific date and time. +- **Advanced** — Runs the scan on a recurring schedule defined by a cron expression. + +**Step 13 –** Click **Complete Setup**. + +## What Happens Next + +Access Analyzer creates the source group and a scan for each domain controller you added. If you selected **Now**, the Active Directory Inventory scan starts immediately. + +To check scan progress, navigate to **Configuration** > **Scan Executions**. + +To view results after the scan completes, see [Active Directory Dashboard](../../dashboards-reports/active-directory-dashboard/overview.md). + +## Edit a Source Group + +To modify an existing Active Directory source group, navigate to **Configuration** > **Source Groups**, select the source group, and click **Edit**. The wizard reopens with your current configuration pre-populated. You can update the source group name, service account, domain controllers, and scan schedule. + +:::note +Updating the service account affects all domain controllers in the source group, as they share a single set of credentials. +::: diff --git a/docs/accessanalyzer/2601/gettingstarted/activity-data/_category_.json b/docs/accessanalyzer/2601/gettingstarted/activity-data/_category_.json deleted file mode 100644 index e008bc29bf..0000000000 --- a/docs/accessanalyzer/2601/gettingstarted/activity-data/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Collecting Activity Data", - "position": 70, - "collapsed": true, - "collapsible": true -} diff --git a/docs/accessanalyzer/2601/gettingstarted/activity-data/file-server-activity.md b/docs/accessanalyzer/2601/gettingstarted/activity-data/file-server-activity.md deleted file mode 100644 index 41114e0caa..0000000000 --- a/docs/accessanalyzer/2601/gettingstarted/activity-data/file-server-activity.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "File Server Activity" -description: "Start collecting file server activity data" -sidebar_position: 10 ---- - -# File Server Activity - -*Content coming soon.* diff --git a/docs/accessanalyzer/2601/gettingstarted/activity-monitor-integration/_category_.json b/docs/accessanalyzer/2601/gettingstarted/activity-monitor-integration/_category_.json deleted file mode 100644 index 130074f727..0000000000 --- a/docs/accessanalyzer/2601/gettingstarted/activity-monitor-integration/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Activity Monitor Integration", - "position": 80, - "collapsed": true, - "collapsible": true -} diff --git a/docs/accessanalyzer/2601/gettingstarted/activity-monitor-integration/overview.md b/docs/accessanalyzer/2601/gettingstarted/activity-monitor-integration/overview.md deleted file mode 100644 index b76c72252c..0000000000 --- a/docs/accessanalyzer/2601/gettingstarted/activity-monitor-integration/overview.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Activity Monitor Integration" -description: "Configure Activity Monitor integration with Access Analyzer" -sidebar_position: 10 ---- - -# Activity Monitor Integration - -*Content coming soon.* diff --git a/docs/accessanalyzer/2601/gettingstarted/entra-id-sync/entra-id.md b/docs/accessanalyzer/2601/gettingstarted/entra-id-sync/entra-id.md deleted file mode 100644 index 787bb89c41..0000000000 --- a/docs/accessanalyzer/2601/gettingstarted/entra-id-sync/entra-id.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Entra ID Source Group" -description: "Making changes to an Entra ID source group wizard workflow" -sidebar_position: 30 ---- - -# Entra ID Source Group - -*Content coming soon.* diff --git a/docs/accessanalyzer/2601/gettingstarted/entra-id-sync/_category_.json b/docs/accessanalyzer/2601/gettingstarted/entra-id/_category_.json similarity index 67% rename from docs/accessanalyzer/2601/gettingstarted/entra-id-sync/_category_.json rename to docs/accessanalyzer/2601/gettingstarted/entra-id/_category_.json index b4785d5d62..03206793dc 100644 --- a/docs/accessanalyzer/2601/gettingstarted/entra-id-sync/_category_.json +++ b/docs/accessanalyzer/2601/gettingstarted/entra-id/_category_.json @@ -1,5 +1,5 @@ { - "label": "Scanning Entra ID", + "label": "Entra ID", "position": 40, "collapsed": true, "collapsible": true diff --git a/docs/accessanalyzer/2601/gettingstarted/entra-id/entra-id.md b/docs/accessanalyzer/2601/gettingstarted/entra-id/entra-id.md new file mode 100644 index 0000000000..9465add534 --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/entra-id/entra-id.md @@ -0,0 +1,34 @@ +--- +title: "Entra ID Scanning Overview" +description: "Overview of Entra ID scanning capabilities and prerequisites in Access Analyzer" +sidebar_position: 1 +--- + +# Entra ID Scanning Overview + +Access Analyzer connects to Microsoft Entra ID to synchronize Microsoft Information Protection (MIP) sensitivity labels from your tenant. These labels — assigned through Microsoft Purview — are applied to files on Windows file servers and appear alongside Access Analyzer's own sensitive data findings. Integrating MIP labels gives you a unified view of sensitive data classification that spans both Access Analyzer's built-in classifiers and your organization's custom Purview sensitivity taxonomy. + +## Prerequisites + +Before setting up an Entra ID source group, confirm that your environment meets the requirements below. The source group wizard connects to Microsoft Entra ID over HTTPS using a registered application's client credentials, so the Access Analyzer server must be able to reach the Microsoft identity platform and an app registration must be configured in your tenant with the required API permissions. + +### Service Account + +Access Analyzer uses a Client ID and Secret service account to authenticate with Microsoft Entra ID via the Microsoft Graph API. This requires a registered application in your Entra ID tenant with the appropriate API permissions granted and a client secret generated for that application. + +See [Entra ID Service Account](../../configurations/service-accounts/entra-id.md) to create the service account and [Entra ID Requirements](../../connectors/entra-id/overview.md) for instructions on registering the application and granting the required permissions. + +### Network Requirements + +| Protocol | Port | Destination | +| --- | --- | --- | +| HTTPS | 443 | Microsoft identity platform (`login.microsoftonline.com`) | +| HTTPS | 443 | Microsoft Graph API (`graph.microsoft.com`) | + +### Before You Begin + +- A registered application in your Entra ID tenant with the required API permissions granted. +- The application's **Tenant ID** and **Client ID**. +- A client secret generated for the application. +- A Client ID and Secret service account created in Access Analyzer. +- Network connectivity from the Access Analyzer server to port 443 confirmed. diff --git a/docs/accessanalyzer/2601/gettingstarted/entra-id/scanning-options.md b/docs/accessanalyzer/2601/gettingstarted/entra-id/scanning-options.md new file mode 100644 index 0000000000..0edc749d8a --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/entra-id/scanning-options.md @@ -0,0 +1,11 @@ +--- +title: "Available Scanning Options" +description: "Available scan types for Entra ID source groups" +sidebar_position: 2 +--- + +# Available Scanning Options + +| Scan Option | Description | Available Configurations | +| --- | --- | --- | +| **Users, Groups, and Roles** | Scans Entra ID users, groups, and role assignments. The first scan runs in full; subsequent scans run differentially, collecting only changes since the last run. | None | diff --git a/docs/accessanalyzer/2601/gettingstarted/entra-id/set-up-source-group.md b/docs/accessanalyzer/2601/gettingstarted/entra-id/set-up-source-group.md new file mode 100644 index 0000000000..678964f440 --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/entra-id/set-up-source-group.md @@ -0,0 +1,45 @@ +--- +title: "Set Up Entra ID Source Group" +description: "Configure an Entra ID source group in Access Analyzer" +sidebar_position: 3 +--- + +# Set Up Entra ID Source Group + +**Step 1 –** Navigate to **Configuration** > **Source Groups** and click **Add Source**. The source group wizard opens. + +**Step 2 –** Select **Entra ID** and click **Next**. + +**Step 3 –** Enter a **Source Group Name**. + +**Step 4 –** Select a service account from the **Service Account** dropdown, or click **+** to create one inline. Entra ID requires a **Client ID and Secret** service account type. See [Service Accounts](../../configurations/service-accounts/overview.md) for details. + +**Step 5 –** Enter the **Tenant ID** for your Entra ID directory. This must be a valid UUID (for example, `550e8400-e29b-41d4-a716-446655440000`). + +**Step 6 –** Click **Test Connection** to verify that Access Analyzer can authenticate to your Entra ID tenant. Resolve any failures before proceeding. + +**Step 7 –** Click **Next**. + +**Step 8 –** Under **Scanner Location**, the scanner is set to **System scanner** and cannot be changed. Entra ID scans run from the Access Analyzer service only. + +**Step 9 –** Under **Scan Schedule**, select when to run the scan: + +- **Now** — Starts the scan immediately after setup completes. +- **At** — Runs the scan once at a specific date and time. +- **Advanced** — Runs the scan on a recurring schedule defined by a cron expression. + +**Step 10 –** Click **Complete Setup**. + +## What Happens Next + +Access Analyzer creates the source group and begins syncing users, groups, and roles from your Entra ID tenant. If you selected **Now**, the scan starts immediately. + +To check scan progress, navigate to **Configuration** > **Scan Executions**. + +## Edit a Source Group + +To modify an existing Entra ID source group, navigate to **Configuration** > **Source Groups**, select the source group, and click **Edit**. The wizard reopens with your current configuration pre-populated. You can update the source group name, service account, tenant ID, and scan schedule. + +:::note +Updating the service account replaces the client credentials used to authenticate with Entra ID. Ensure the new service account has the required API permissions before saving. +::: diff --git a/docs/accessanalyzer/2601/gettingstarted/file-server-scans/file-server.md b/docs/accessanalyzer/2601/gettingstarted/file-server-scans/file-server.md deleted file mode 100644 index 7186761125..0000000000 --- a/docs/accessanalyzer/2601/gettingstarted/file-server-scans/file-server.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "File Server Source Group" -description: "Making changes to a File Server source group wizard workflow" -sidebar_position: 20 ---- - -# File Server Source Group - -*Content coming soon.* diff --git a/docs/accessanalyzer/2601/gettingstarted/file-server-scans/_category_.json b/docs/accessanalyzer/2601/gettingstarted/file-servers/_category_.json similarity index 64% rename from docs/accessanalyzer/2601/gettingstarted/file-server-scans/_category_.json rename to docs/accessanalyzer/2601/gettingstarted/file-servers/_category_.json index 4771d2c62e..dbe2c40136 100644 --- a/docs/accessanalyzer/2601/gettingstarted/file-server-scans/_category_.json +++ b/docs/accessanalyzer/2601/gettingstarted/file-servers/_category_.json @@ -1,5 +1,5 @@ { - "label": "Scanning File Servers", + "label": "File Servers", "position": 30, "collapsed": true, "collapsible": true diff --git a/docs/accessanalyzer/2601/gettingstarted/file-servers/file-servers.md b/docs/accessanalyzer/2601/gettingstarted/file-servers/file-servers.md new file mode 100644 index 0000000000..18cefa7115 --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/file-servers/file-servers.md @@ -0,0 +1,31 @@ +--- +title: "File Server Scanning Overview" +description: "Overview of file server scanning capabilities and prerequisites in Access Analyzer" +sidebar_position: 1 +--- + +# File Server Scanning Overview + +Access Analyzer scans file servers over SMB to map share permissions, folder-level ACLs, and file ownership across your environment. It can also scan file contents to locate sensitive data and, if activity monitoring is configured, track file access events over time. Reports surface open access, broken inheritance, direct user permissions, and sensitive data exposure — giving security and compliance teams the visibility they need to reduce unnecessary access and meet data protection requirements. + +## Prerequisites + +Before setting up a file server source group, confirm that your environment meets the requirements below. The source group wizard connects to your Windows file servers over SMB, so the Access Analyzer server must be able to reach them on the network and a domain service account must be available with the permissions required for the scan types you plan to enable. + +### Service Account + +Access Analyzer uses a domain service account to authenticate against your Windows file servers over SMB and enumerate shares, permissions, and file contents. The account must be a member of the same domain as the target file servers. The specific permissions required depend on the scan types you enable — access scanning and sensitive data scanning have different requirements. + +See [Username and Password](../../configurations/service-accounts/username-password.md) to create the service account and [CIFS / SMB File Share](../../connectors/file-servers/cifs.md) for the full list of required permissions by scan type. + +### Network Requirements + +| Protocol | Port | Destination | +| --- | --- | --- | +| SMB | 445 | Windows file servers in the source group | + +### Before You Begin + +- The hostname or IP address of each file server you plan to add. +- A Username and Password service account created in Access Analyzer with the appropriate permissions on the target file servers. +- Network connectivity from the Access Analyzer server to port 445 on each file server confirmed. diff --git a/docs/accessanalyzer/2601/gettingstarted/file-servers/reports.md b/docs/accessanalyzer/2601/gettingstarted/file-servers/reports.md new file mode 100644 index 0000000000..9d23d9f9b4 --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/file-servers/reports.md @@ -0,0 +1,31 @@ +--- +title: "Reports" +description: "Pre-built reports available for File Servers source groups in Access Analyzer" +sidebar_position: 50 +--- + +# Reports + +File Servers source groups include a set of pre-built reports that answer common security questions about permissions, sensitive data exposure, access patterns, and data content across your CIFS/SMB file shares. Reports are available under the Reports section after the first scan completes and update each time a scan runs. + +## Available reports + +| Location | Report | Description | +|----------|--------|-------------| +| Access / Broken Inheritance | Broken Inheritance | Lists shares and folders where permission inheritance has been broken, meaning the folder's ACL no longer follows its parent. Use this report to find locations where custom permission assignments may have introduced inconsistencies or unexpected access. | +| Access / Domain User ACLs | Domain User ACLs | Shows share and folder permissions assigned directly to domain user accounts. Use this report to identify accounts with direct ACL entries that should be managed through groups instead. | +| Access / High Risk ACLs | High Risk ACLs | Identifies folders where broad trustees such as Everyone, Authenticated Users, or Domain Users appear in the access control list. Use this report to locate and remediate over-permissioned folders that expose data to wide audiences. | +| Access / Local Administrators | Local Administrators | Lists local administrator accounts and the hosts where they hold that privilege. Use this report to identify non-standard or unauthorized local administrator assignments across your file servers. | +| Access / Missing Full Control | Missing Full Control | Lists folders where no trustee holds Full Control permission. Use this report to identify folders that may lack a clear owner or administrator and address potential access management gaps. | +| Access / Open Access | Open Access | Identifies folders and shares accessible to broad groups or where sensitive data is reachable without restriction. Use this report to prioritize remediation of the most exposed locations in your file server environment. | +| Access / Probable Owner | Probable Owner | Identifies the most likely owner for each share based on access patterns and file activity. Use this report to assign data ownership and support data governance workflows. | +| Access / Share Audit | Share Audit | Provides a detailed breakdown of share-level attributes including scan status, last scanned date, file counts, object counts, and active users. Use this report to confirm scan coverage and review the overall state of each share. | +| Activity / Activity Investigation | Activity Investigation | Displays file system events filtered by date range, user, path, and event type. Use this report to trace the actions of a specific user or investigate changes to a specific file or folder. | +| Content / Empty Shares | Empty Shares | Lists shares that contain no files. Use this report to identify shares that can be reviewed for decommissioning or consolidation. | +| Content / Largest Shares | Largest Shares | Ranks file shares by total size. Use this report to identify shares that consume the most storage and prioritize them for review or cleanup. | +| Content / Nested Shares | Nested Shares | Identifies shares that are nested inside other shares, creating multiple access paths to the same data with potentially different permissions. Use this report to find and resolve configurations that complicate permission management and access auditing. | +| Content / Stale Content | Stale Content | Identifies files and shares that haven't been accessed within a configurable threshold. Use this report to locate data that may be a candidate for archiving, deletion, or access review. | +| Sensitive Data / Sensitive Data Activity | Sensitive Data Activity | Shows file system events involving files that contain sensitive data, filtered by date range, event type, user, and classification taxonomy. Use this report to identify who is reading, modifying, or deleting sensitive files and to detect potential data exfiltration or misuse. | +| Sensitive Data / Sensitive Data Overview | Sensitive Data Overview | Provides a high-level summary of sensitive data scan findings across CIFS/SMB file shares, including the number of files with matches, classification terms found, and distribution by host and share. Use this report as a starting point for understanding where sensitive data lives in your file server environment. | +| Sensitive Data / Share Audit | Share Audit | Shows share-level details in the context of sensitive data findings, including which shares contain files with sensitive data matches. Use this report to understand sensitive data distribution across shares and prioritize remediation. | +| Sensitive Data / Stale Data | Stale Data | Identifies files containing sensitive data that haven't been accessed recently. Use this report to find aging sensitive content that may no longer be actively used but still carries exposure risk. | diff --git a/docs/accessanalyzer/2601/gettingstarted/file-servers/scanning-options.md b/docs/accessanalyzer/2601/gettingstarted/file-servers/scanning-options.md new file mode 100644 index 0000000000..c80cdd296d --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/file-servers/scanning-options.md @@ -0,0 +1,28 @@ +--- +title: "Available Scanning Options" +description: "Available scan types and configuration options for file server source groups" +sidebar_position: 2 +--- + +# Available Scanning Options + +| Scan Option | Description | Available Configurations | +| --- | --- | --- | +| **Access** | Scans file server permissions and access controls to identify who has access to what. | Share selection (all shares or custom), file-level permissions, concurrent workers (1–20) | +| **Sensitive Data** | Scans file contents for sensitive data patterns such as PII, credentials, PHI, and financial records. The first scan runs in full; subsequent scans run differentially, collecting only changes since the last run. | Share selection (all shares or custom), sensitive data types, OCR, differential scan | + +## Scan Configuration + +**Access** + +- **Include Shares** — Select **All shares** to scan every share on the server, or **Custom selection** to specify which shares to include. +- **Exclude Shares** — Enter share paths to skip. Wildcards are supported (for example, `\\fileserver\*\temp*`). +- **Hidden shares** — Select **Automatically enumerate hidden shares** to include hidden shares. Use **Exclude Hidden Shares** to skip specific ones (for example, `ADMIN$, C$, IPC$`). +- **File-level permissions** — Select **Include file-level permission data** to collect permissions at the individual file level in addition to folder level. This increases scan time. +- **Workers** — Sets the number of concurrent enumeration threads. Default is `3`; valid range is `1–20`. Increase to improve scan speed; decrease to reduce load on the file server. + +**Sensitive Data** + +- **Include/Exclude Shares** — Same share selection options as the Access scan. +- **Sensitive data types** — Select **Inherit from Global Settings** to use the system-wide classification configuration, or disable this option to configure types for this source group. Enable each type you want to detect and assign a classification label. +- **OCR** — Select **Run OCR** to scan images, screenshots, and scanned documents for sensitive text. This increases processing time. diff --git a/docs/accessanalyzer/2601/gettingstarted/file-servers/schema-reference.md b/docs/accessanalyzer/2601/gettingstarted/file-servers/schema-reference.md new file mode 100644 index 0000000000..47e0de6ab2 --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/file-servers/schema-reference.md @@ -0,0 +1,201 @@ +--- +title: "File Servers Schema Reference" +sidebar_position: 40 +--- + +# File Servers Schema Reference + +Access Analyzer stores File Server scan data in the `access_analyzer` ClickHouse database. The tables below are created when you set up a File Server source group and run a scan. Use this reference when querying scan data directly or integrating Access Analyzer data with external tools. + +:::note +All tables use the `ReplacingMergeTree` engine. Duplicate rows with the same primary key are deduplicated at merge time. Query the `_latest` views to return only the most recent version of each record. +::: + +## Metadata columns + +All tables include the following columns populated by Access Analyzer during each scan: + +| Column | Type | Description | +|--------|------|-------------| +| `scan_id` | `String` | Identifier of the source group that produced this record. | +| `scan_execution_id` | `String` | Identifier of the specific scan run. | +| `scanned_at` | `DateTime` | Timestamp when the record was written. | + +--- + +## Tables + +### cifs_object + +Stores the file system inventory collected during a scan — one row per file, directory, or share discovered on a file server. + +| Column | Type | Description | +|--------|------|-------------| +| `host` | `String` | Hostname of the file server. | +| `share_name` | `String` | Name of the share on the file server. | +| `share_path` | `String` | UNC path of the share root. | +| `path` | `String` | Full path of the object within the share. | +| `object_type` | `Enum8('FILE', 'DIRECTORY', 'SHARE')` | Whether the object is a file, directory, or share. | +| `parent_path` | `String` | Full path of the parent directory. | +| `name` | `String` | Name of the file or directory. | +| `file_extension` | `String` | File extension, if applicable. Empty string for directories and shares. | +| `file_size` | `UInt64` | Size of the file in bytes. Zero for directories and shares. | +| `owner_sid` | `String` | SID of the file or directory owner. | +| `group_owner_sid` | `String` | SID of the primary group owner. | +| `created_time` | `Nullable(DateTime)` | Optional. Timestamp when the object was created. | +| `modified_time` | `Nullable(DateTime)` | Optional. Timestamp when the object was last modified. | +| `accessed_time` | `Nullable(DateTime)` | Optional. Timestamp when the object was last accessed. | +| `scan_status` | `Enum8('SUCCESS', 'ERROR')` | Whether the object was scanned successfully. | +| `error_message` | `String` | Error detail if `scan_status` is `ERROR`. Empty string on success. | +| `attributes` | `Array(Enum8('DIRECTORY', 'READONLY', 'HIDDEN', 'SYSTEM', 'ARCHIVE', 'COMPRESSED', 'ENCRYPTED'))` | Windows file attributes applied to the object. | +| `inheritance_flags` | `UInt16` | Bitmask representing ACL inheritance settings on the object. | +| `is_protected` | `Nullable(Bool)` | Optional. Whether the object's ACL is protected from inheritance. | +| `is_world_readable` | `Nullable(Bool)` | Optional. Whether any well-known open SID (for example, Everyone) has read access. | +| `is_world_writable` | `Nullable(Bool)` | Optional. Whether any well-known open SID has write access. | +| `is_admin_only` | `Nullable(Bool)` | Optional. Whether access is restricted to administrative accounts only. | +| `has_explicit_deny` | `Nullable(Bool)` | Optional. Whether the object has at least one explicit deny ACE. | +| `permission_count` | `UInt16` | Total number of ACEs on the object. | +| `unique_trustees_count` | `UInt16` | Number of distinct trustees with permissions on the object. | +| `permission_flags` | `UInt16` | Bitmask summarizing the permission state of the object. | +| `is_complete` | `Bool` | Whether the scan fully enumerated this object's permissions before the scan completed. | +| `hard_delete` | `Bool` | Internal flag used by `ReplacingMergeTree` to exclude deleted rows. Rows where `hard_delete = 1` are suppressed at query time when querying with `FINAL`. | + +**Relations** + +| Related table | Join column | Description | +|---------------|-------------|-------------| +| `cifs_permission` | `host`, `share_name`, `path` | Resolves NTFS permissions assigned to this file or directory. | +| `cifs_sensitive_data` | `host`, `share_name`, `path` | Resolves sensitive data findings for this file. | + +--- + +### cifs_permission + +Stores NTFS ACEs (access control entries) for files and directories — one row per trustee per path. + +| Column | Type | Description | +|--------|------|-------------| +| `trustee_sid` | `String` | SID of the user or group that this ACE grants or denies access to. | +| `host` | `String` | Hostname of the file server. | +| `share_name` | `String` | Name of the share containing the object. | +| `path` | `String` | Full path of the object this ACE applies to. | +| `permissions` | `Array(Enum8('FILE_READ_DATA', 'FILE_WRITE_DATA', 'FILE_APPEND_DATA', 'FILE_READ_EA', 'FILE_WRITE_EA', 'FILE_EXECUTE', 'FILE_DELETE_CHILD', 'FILE_READ_ATTRIBUTES', 'FILE_WRITE_ATTRIBUTES', 'DIR_LIST', 'DIR_ADD_FILE', 'DIR_ADD_SUB_DIR', 'DIR_DELETE_CHILD', 'DELETE', 'READ_CONTROL', 'WRITE_DAC', 'WRITE_OWNER', 'GENERIC_ALL', 'GENERIC_EXECUTE', 'GENERIC_WRITE', 'GENERIC_READ'))` | Individual permission flags included in this ACE. | +| `normalized_permissions` | `FixedString(6)` | Six-character string encoding the effective permissions (for example, `RWXDMC`) for use in summary queries. | +| `access_type` | `Enum8('ALLOW', 'DENY')` | Whether this ACE allows or denies access. | +| `access_mask` | `UInt32` | Raw Windows access mask bitmask for this ACE. | +| `inheritance_flags` | `UInt16` | Bitmask describing how this ACE propagates to child objects. | +| `is_inherited` | `Bool` | Whether this ACE was inherited from a parent object rather than set explicitly. | +| `mip_label_id` | `Nullable(String)` | Optional. Microsoft GUID of the MIP sensitivity label applied to this object. | +| `mip_label_name` | `Nullable(String)` | Optional. Display name of the MIP sensitivity label applied to this object. | +| `hard_delete` | `Bool` | Internal flag used by `ReplacingMergeTree` to exclude deleted rows. | + +**Relations** + +| Related table | Join column | Description | +|---------------|-------------|-------------| +| `cifs_object` | `host`, `share_name`, `path` | Resolves file system object details for this ACE. | +| `cifs_share_permission` | `host`, `share_name` | Resolves the share-level permissions that apply in combination with this NTFS ACE. | + +--- + +### cifs_share_permission + +Stores share-level ACEs — one row per trustee per share. Share permissions apply in addition to NTFS permissions; the effective access a user has is the intersection of both. + +| Column | Type | Description | +|--------|------|-------------| +| `trustee_sid` | `String` | SID of the user or group that this share ACE grants or denies access to. | +| `host` | `String` | Hostname of the file server. | +| `share_name` | `String` | Name of the share this ACE applies to. | +| `permissions` | `Array(Enum8('FILE_READ_DATA', 'FILE_WRITE_DATA', 'FILE_APPEND_DATA', 'FILE_READ_EA', 'FILE_WRITE_EA', 'FILE_EXECUTE', 'FILE_DELETE_CHILD', 'FILE_READ_ATTRIBUTES', 'FILE_WRITE_ATTRIBUTES', 'DIR_LIST', 'DIR_ADD_FILE', 'DIR_ADD_SUB_DIR', 'DIR_DELETE_CHILD', 'DELETE', 'READ_CONTROL', 'WRITE_DAC', 'WRITE_OWNER', 'GENERIC_ALL', 'GENERIC_EXECUTE', 'GENERIC_WRITE', 'GENERIC_READ'))` | Individual permission flags included in this share ACE. | +| `normalized_permissions` | `FixedString(6)` | Six-character string encoding the effective permissions for use in summary queries. | +| `access_type` | `Enum8('ALLOW', 'DENY')` | Whether this ACE allows or denies access at the share level. | +| `access_mask` | `UInt32` | Raw Windows access mask bitmask for this share ACE. | +| `mip_label_id` | `Nullable(String)` | Optional. Microsoft GUID of the MIP sensitivity label applied to this share. | +| `mip_label_name` | `Nullable(String)` | Optional. Display name of the MIP sensitivity label applied to this share. | +| `hard_delete` | `Bool` | Internal flag used by `ReplacingMergeTree` to exclude deleted rows. | + +**Relations** + +| Related table | Join column | Description | +|---------------|-------------|-------------| +| `cifs_permission` | `host`, `share_name` | Resolves NTFS ACEs that apply within this share. | + +--- + +### cifs_sensitive_data + +Stores sensitive data classification findings — one row per taxonomy term match per file path. + +| Column | Type | Description | +|--------|------|-------------| +| `host` | `String` | Hostname of the file server. | +| `share_name` | `String` | Name of the share containing the file. | +| `path` | `String` | Full path of the file where sensitive data was detected. | +| `taxonomy_name` | `String` | Name of the taxonomy that contains the matched term (for example, `PII`). | +| `term_name` | `String` | Name of the classification term that matched (for example, `Social Security Number`). | +| `processing_time_seconds` | `Float32` | Time in seconds to classify the file. | +| `classification_method` | `Nullable(Enum8('SDK_AUTO', 'SDK_CUSTOM'))` | Optional. Whether detection used the built-in automatic classification engine (`SDK_AUTO`) or a custom classification configuration (`SDK_CUSTOM`). | +| `scan_status` | `Enum8('SUCCESS', 'ERROR')` | Whether the file was processed successfully. `SUCCESS` indicates the file was read and classified, regardless of whether sensitive data was found. `ERROR` indicates a processing failure such as a file conversion error, encryption, or unsupported format. | +| `error_message` | `Nullable(String)` | Optional. Error detail when `scan_status` is `ERROR`. Null on success. | +| `hard_delete` | `Bool` | Internal flag used by `ReplacingMergeTree` to exclude deleted rows. | + +**Relations** + +| Related table | Join column | Description | +|---------------|-------------|-------------| +| `cifs_object` | `host`, `share_name`, `path` | Resolves file system object details for this finding. | +| `cifs_sensitive_data_mip_labels` | `host`, `share_name`, `path` | Resolves MIP sensitivity label decisions applied to this file. | + +--- + +### cifs_sensitive_data_mip_labels + +Stores Microsoft Information Protection (MIP) sensitivity label decisions for files that contain sensitive data findings. Each row records the label action Access Analyzer determined for a file based on its classification results. MIP labels are sourced from an Entra ID source group configured in the same Access Analyzer instance — Access Analyzer uses that source group to resolve label definitions and apply or recommend label changes. + +:::note +This table uses `ReplacingMergeTree(decision_timestamp)` rather than `scanned_at`. The most recent decision per file (identified by `source_id`, `host`, `share_name`, and `path`) is kept at merge time. +::: + +| Column | Type | Description | +|--------|------|-------------| +| `source_id` | `UUID` | Identifier of the Entra ID source group used to resolve MIP label definitions. | +| `host` | `String` | Hostname of the file server. | +| `share_name` | `String` | Name of the share containing the file. | +| `path` | `String` | Full path of the file this label decision applies to. | +| `mip_is_protected` | `Bool` | Whether the file is currently protected by MIP encryption. | +| `taxonomy_id` | `Nullable(UUID)` | Optional. Identifier of the taxonomy that triggered this label decision. | +| `action` | `Enum8('upgrade', 'keep', 'downgrade', 'clear', 'none')` | The label action Access Analyzer determined: `upgrade` applies a higher-sensitivity label, `downgrade` applies a lower-sensitivity label, `keep` leaves the current label unchanged, `clear` removes the label, and `none` indicates no action was taken. | +| `label_id` | `Nullable(UUID)` | Optional. UUID of the MIP sensitivity label selected by the action. | +| `label_name` | `Nullable(String)` | Optional. Display name of the MIP sensitivity label selected by the action. | +| `reason` | `Nullable(String)` | Optional. Explanation of why this label action was chosen. | +| `decision_timestamp` | `DateTime` | Timestamp when Access Analyzer made this label decision. | +| `scanned_at` | `DateTime` | Timestamp when the record was written. | +| `applied_at` | `Nullable(DateTime)` | Optional. Timestamp when the label was successfully applied to the file. Null if not yet applied. | +| `apply_error` | `String` | Error message if the label application failed. Empty string when no error occurred. | +| `apply_attempts` | `UInt8` | Number of times Access Analyzer has attempted to apply this label decision. | +| `created_at` | `DateTime` | Timestamp when this record was first created. | +| `updated_at` | `DateTime` | Timestamp when this record was last updated. | + +**Relations** + +| Related table | Join column | Description | +|---------------|-------------|-------------| +| `cifs_sensitive_data` | `host`, `share_name`, `path` | Resolves the sensitive data findings that triggered this label decision. | + +--- + +## Views + +Access Analyzer creates views that simplify common queries. Use views in preference to querying base tables directly. + +| View | Base table | Description | +|------|------------|-------------| +| `cifs_object_latest` | `cifs_object` | Returns the most recent version of each file system object, using `FINAL` to suppress duplicates. | +| `cifs_permission_latest` | `cifs_permission` | Returns the most recent version of each NTFS ACE, using `FINAL` to suppress duplicates. | +| `cifs_share_permission_latest` | `cifs_share_permission` | Returns the most recent version of each share-level ACE, using `FINAL` to suppress duplicates. | +| `cifs_sensitive_data_latest` | `cifs_sensitive_data` | Returns one aggregated row per file path, combining all taxonomy and term matches for that path. The `taxonomy_names` and `term_names` columns return arrays of distinct values grouped from individual rows. | +| `cifs_sensitive_data_mip_labels_latest` | `cifs_sensitive_data_mip_labels` | Returns the most recent label decision per file, using `FINAL` to suppress duplicates. | +| `cifs_sensitive_data_mip_labels_summary` | `cifs_sensitive_data_mip_labels` | Returns a summary of label decisions grouped by host, share, action, label name, and protection status. Includes decision counts and the timestamp range of first and last decisions. | +| `cifs_effective_permissions` | `cifs_permission_latest`, `cifs_share_permission_latest` | Joins NTFS and share permissions with resolved principal identities (local users, local groups, Active Directory users, Active Directory groups, and well-known SIDs) to produce one row per principal per path. Use this view to query who has access to a given path by name rather than by SID. | +| `cifs_effective_access` | `cifs_effective_permissions` | Computes the final effective access mask for each principal per path by combining NTFS allow and deny ACEs with share-level permissions. Use this view to determine the actual access a named user or group has to a file or directory. | diff --git a/docs/accessanalyzer/2601/gettingstarted/file-servers/set-up-source-group.md b/docs/accessanalyzer/2601/gettingstarted/file-servers/set-up-source-group.md new file mode 100644 index 0000000000..2994963ece --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/file-servers/set-up-source-group.md @@ -0,0 +1,62 @@ +--- +title: "Set Up File Server Source Group" +description: "Configure a file server source group in Access Analyzer" +sidebar_position: 3 +--- + +# Set Up File Server Source Group + +**Step 1 –** Navigate to **Configuration** > **Source Groups** and click **Add Source**. The source group wizard opens. + +**Step 2 –** Select **File Server** and click **Next**. + +**Step 3 –** Enter a **Source Group Name**. + +**Step 4 –** Select a service account from the **Service Account** dropdown, or click **+** to create one inline. See [Service Accounts](../../configurations/service-accounts/overview.md) for details. + +**Step 5 –** Click **Add** under **File Servers** and enter the server name or IP address of each file server to include. Click **Done** when finished. + +**Step 6 –** Click **Test Connection** to verify connectivity. Each server displays a **Connected** or **Failed** status. Resolve any failures before proceeding. + +**Step 7 –** Click **Next**. + +**Step 8 –** Enable the scan types you want to run: + +**Access scan:** + +- Toggle **Access** to enable scanning of file permissions and access controls. +- Under **Include Shares**, select **All shares** to scan every share on the server, or **Custom selection** to specify a list of shares to include. +- Optionally, add share paths to the **Exclude Shares** field to skip specific locations. Wildcards are supported (for example, `\\fileserver\*\temp*`). +- Select **Automatically enumerate hidden shares** to include hidden shares in the scan. Use the **Exclude Hidden Shares** field to exclude specific hidden shares (for example, `ADMIN$, C$, IPC$`). +- Select **Include file-level permission data** to collect permissions at the file level in addition to folder level. +- Set **Workers** to control the number of concurrent threads used during enumeration. The default is `3`. The valid range is `1–20`. + +**Sensitive Data scan:** + +- Toggle **Sensitive Data** to enable scanning of file contents for sensitive data patterns. +- Configure share selection using the same options as the Access scan above. +- Select **Inherit from Global Settings** to use the sensitive data types configured at the system level, or disable this option to configure types for this source group specifically. +- If configuring types directly, enable each sensitive data type you want to detect and assign a classification label. +- Select **Run OCR** to scan images, screenshots, and scanned documents for sensitive text. This increases processing time. + +**Step 9 –** Under **Scanner Location**, select **System scanner** to run scans from the Access Analyzer service, or select **Custom scanner** to use a deployed scanner. See [Scanners](../../configurations/source-groups/scanners/overview.md) for details. + +**Step 10 –** Under **Scan Schedule**, select when to run the scan: + +- **Now** — Starts the scan immediately after setup completes. +- **At** — Runs the scan once at a specific date and time. +- **Advanced** — Runs the scan on a recurring schedule defined by a cron expression. + +**Step 11 –** Click **Complete Setup**. + +## What Happens Next + +Access Analyzer creates the source group and a scan for each file server you added. If you selected **Now**, the enabled scans start immediately. + +To check scan progress, navigate to **Configuration** > **Scan Executions**. + +To view results after the scan completes, see [Data Security Dashboard](../../dashboards-reports/data-security-dashboard/overview.md). + +## Edit a Source Group + +To modify an existing file server source group, navigate to **Configuration** > **Source Groups**, select the source group, and click **Edit**. The wizard reopens with your current configuration pre-populated. You can update the source group name, service account, file servers, and scan settings. diff --git a/docs/accessanalyzer/2601/gettingstarted/first-service-account.md b/docs/accessanalyzer/2601/gettingstarted/first-service-account.md deleted file mode 100644 index f58efefd6c..0000000000 --- a/docs/accessanalyzer/2601/gettingstarted/first-service-account.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Setting Up a Service Account" -description: "Create a service account to connect to data sources" -sidebar_position: 1 ---- - -# Setting Up a Service Account - -*Content coming soon.* diff --git a/docs/accessanalyzer/2601/gettingstarted/sharepoint-online-scan/sharepoint-online.md b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online-scan/sharepoint-online.md deleted file mode 100644 index 0b81d403ff..0000000000 --- a/docs/accessanalyzer/2601/gettingstarted/sharepoint-online-scan/sharepoint-online.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "SharePoint Online Source Group" -description: "Making changes to a SharePoint Online source group wizard workflow" -sidebar_position: 40 ---- - -# SharePoint Online Source Group - -*Content coming soon.* diff --git a/docs/accessanalyzer/2601/gettingstarted/sharepoint-online-scan/_category_.json b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/_category_.json similarity index 61% rename from docs/accessanalyzer/2601/gettingstarted/sharepoint-online-scan/_category_.json rename to docs/accessanalyzer/2601/gettingstarted/sharepoint-online/_category_.json index 23057cd793..a8d05dd13b 100644 --- a/docs/accessanalyzer/2601/gettingstarted/sharepoint-online-scan/_category_.json +++ b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/_category_.json @@ -1,5 +1,5 @@ { - "label": "Scanning SharePoint Online", + "label": "SharePoint Online", "position": 50, "collapsed": true, "collapsible": true diff --git a/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/reports.md b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/reports.md new file mode 100644 index 0000000000..0c969c2a49 --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/reports.md @@ -0,0 +1,17 @@ +--- +title: "Reports" +description: "Pre-built reports available for SharePoint Online source groups in Access Analyzer" +sidebar_position: 50 +--- + +# Reports + +After the first scan of a SharePoint Online source group completes, three pre-built reports become available under the Reports section. These reports help you answer key security questions about your SharePoint environment: which files carry sensitive data, how broadly content is shared, and where stale or redundant data accumulates across your sites. + +## Available reports + +| Location | Report | Description | +|----------|--------|-------------| +| Access / Shared Links Report | Shared Links Report | Shows all sharing links across your SharePoint environment, with breakdowns by sharing scope (organization, anonymous, specific people), active status, sensitive data type, and site. Use this report to identify overly broad sharing and links that expose sensitive files. | +| Content / ROT Analysis | ROT Analysis | Identifies Redundant, Obsolete, and Trivial (ROT) data across your SharePoint sites, including stale files not modified in over a year, duplicate files by content hash, and stale files containing sensitive data. Use this report to prioritize data cleanup and reduce unnecessary exposure of aging content. | +| Content / Scan Overview | Scan Overview | Summarizes the results of the most recent scan across all sites, including total site count, file count, total storage, and files with sensitive data. Use this report to confirm scan coverage and quickly identify which sites hold the most sensitive content. | diff --git a/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/scanning-options.md b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/scanning-options.md new file mode 100644 index 0000000000..6c89115485 --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/scanning-options.md @@ -0,0 +1,17 @@ +--- +title: "Available Scanning Options" +description: "Available scan types and configuration options for SharePoint Online source groups" +sidebar_position: 2 +--- + +# Available Scanning Options + +| Scan Option | Description | Available Configurations | +| --- | --- | --- | +| **SharePoint Online Access** | Scans SharePoint Online sites for permissions and access controls. The first scan runs in full; subsequent scans run differentially, collecting only changes since the last run. | Site URLs (optional — leave empty to scan all sites) | + +## Scan Configuration + +**SharePoint Online Access** + +- **Site URLs** — Leave empty to scan all sites in the tenant, or enter specific site URLs to limit the scan to a subset of your SharePoint Online environment. diff --git a/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/schema-reference.md b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/schema-reference.md new file mode 100644 index 0000000000..fa0d681ea2 --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/schema-reference.md @@ -0,0 +1,166 @@ +--- +title: "SharePoint Online Schema Reference" +sidebar_position: 40 +--- + +# SharePoint Online Schema Reference + +Access Analyzer stores SharePoint Online scan data in the `access_analyzer` ClickHouse database. The tables below are created when you set up a SharePoint Online source group and run a scan. Use this reference when querying scan data directly or integrating Access Analyzer data with external tools. + +:::note +All tables use the `ReplacingMergeTree` engine. Duplicate rows with the same primary key are deduplicated at merge time. Query the `_latest` views to return only the most recent version of each record. +::: + +## Metadata columns + +All tables include the following columns populated by Access Analyzer during each scan: + +| Column | Type | Description | +|--------|------|-------------| +| `scan_id` | `String` | Identifier of the source group that produced this record. | +| `scan_execution_id` | `String` | Identifier of the specific scan run. | +| `scanned_at` | `DateTime` | Timestamp when the record was written. | + +--- + +## Tables + +### sharepoint_online_objects + +Stores one row per scanned SharePoint item — sites, lists, document libraries, and list items (files and folders). + +| Column | Type | Description | +|--------|------|-------------| +| `site_hostname` | `String` | Hostname of the SharePoint site collection (for example, `contoso.sharepoint.com`). | +| `site_id` | `String` | SharePoint identifier of the site collection. | +| `item_id` | `String` | Unique identifier of the item within the site. | +| `site_url` | `String` | Absolute URL of the site collection. | +| `drive_id` | `String` | Microsoft Graph drive identifier for the document library that contains this item. Empty for sites and lists that do not have a drive. | +| `drive_item_id` | `String` | Microsoft Graph drive item identifier. Empty for items that are not drive items. | +| `item_type` | `Enum8` | Type of SharePoint item. Values: `SITE`, `LIST`, `LIBRARY`, `LIST_ITEM`. | +| `name` | `String` | Display name of the item. | +| `file_extension` | `String` | File extension, including the leading period (for example, `.docx`). Empty for non-file items. | +| `relative_url` | `String` | Server-relative URL path of the item. | +| `file_size` | `Nullable(Int64)` | Optional. File size in bytes. Null for items that are not files. | +| `created_time` | `DateTime` | Timestamp when the item was created in SharePoint. | +| `created_by_id` | `String` | SharePoint user identifier of the user who created the item. | +| `created_by_email` | `String` | Email address of the user who created the item. | +| `modified_time` | `DateTime` | Timestamp of the most recent modification. | +| `modified_by_id` | `String` | SharePoint user identifier of the user who last modified the item. | +| `modified_by_email` | `String` | Email address of the user who last modified the item. | +| `parent_item_id` | `String` | `item_id` of the parent item. Empty for top-level sites. | +| `scan_status` | `String` | Result of scanning this item. Typical values: `SUCCESS`, `ERROR`. | +| `error_message` | `String` | Error detail when `scan_status` is `ERROR`. Empty on success. | +| `is_complete` | `Boolean` | Indicates whether the scan wrote all expected records for this item. Used internally to support scan resume. | + +**Primary key:** `(site_hostname, site_id, item_id)` + +**Relations** + +| Related table | Join columns | Description | +|---|---|---| +| `sharepoint_online_permissions` | `site_hostname`, `site_id`, `item_id` | All permissions assigned to this item. | +| `sharepoint_online_shared_links` | `site_hostname`, `site_id`, `item_id` | All sharing links created for this item. | +| `sharepoint_online_sensitive_data` | `drive_id`, `drive_item_id` | Classification results for this item. Only populated for drive items. | + +--- + +### sharepoint_online_permissions + +Stores one row per permission assignment. Each row represents a single principal (user or group) having a specific permission on a specific item. + +| Column | Type | Description | +|--------|------|-------------| +| `site_hostname` | `String` | Hostname of the site collection that contains the item. | +| `site_id` | `String` | SharePoint identifier of the site collection. | +| `item_id` | `String` | Identifier of the item this permission applies to. | +| `permission_id` | `String` | SharePoint identifier of the permission entry. | +| `share_id` | `String` | Identifier of the sharing link that granted this permission. Empty for direct permissions. | +| `principal_id` | `String` | Identifier of the user or group that holds the permission. | +| `principal_type` | `Enum8` | Type of the principal. Values: `USER`, `GROUP`, `SITE_USER`, `SITE_GROUP`. | +| `principal_name` | `String` | Display name of the principal. | +| `principal_email` | `String` | Email address of the principal. Empty for groups that do not have an email address. | +| `permission_type` | `Enum8` | How the permission was granted. Values: `DIRECT` (assigned directly to the item), `SHARED` (granted through a sharing link). | +| `permission_levels` | `Array(Enum8)` | Named permission levels assigned to the principal. Values: `OWNER`, `READ`, `WRITE`. | +| `effective_base_permissions` | `Array(Enum8)` | Full set of granular SharePoint base permissions the principal holds. Values include `VIEW_LIST_ITEMS`, `ADD_LIST_ITEMS`, `EDIT_LIST_ITEMS`, `DELETE_LIST_ITEMS`, `MANAGE_LISTS`, `MANAGE_PERMISSIONS`, `MANAGE_WEB`, and others as defined by the SharePoint permission model. | +| `normalized_permissions` | `FixedString(5)` | Compact bitmask representation of the permission levels. Used internally for permission comparison. | +| `parent_site_id` | `String` | Identifier of the site collection from which this permission is inherited. Empty for permissions that are not inherited. | +| `parent_item_id` | `String` | `item_id` of the item from which this permission is inherited. Empty for permissions assigned directly to this item. | +| `is_site_admin` | `Bool` | `true` if the principal is a site collection administrator. | +| `is_external_user` | `Bool` | `true` if the principal is a guest or external user. | +| `mip_label_id` | `Nullable(String)` | Optional. Microsoft GUID of the Microsoft Information Protection sensitivity label applied to the SharePoint item at the time of the scan. | +| `mip_label_name` | `Nullable(String)` | Optional. Display name of the sensitivity label identified by `mip_label_id`. | + +**Primary key:** `(site_hostname, site_id, item_id, permission_id, principal_id)` + +**Relations** + +| Related table | Join columns | Description | +|---|---|---| +| `sharepoint_online_objects` | `site_hostname`, `site_id`, `item_id` | The item this permission applies to. | +| `sharepoint_online_shared_links` | `site_hostname`, `site_id`, `item_id`, `share_id` | The sharing link that granted this permission, when `permission_type` is `SHARED`. | + +--- + +### sharepoint_online_shared_links + +Stores one row per sharing link. A sharing link may grant access to one or more principals; the corresponding permission rows appear in `sharepoint_online_permissions`. + +| Column | Type | Description | +|--------|------|-------------| +| `site_hostname` | `String` | Hostname of the site collection that contains the item. | +| `site_id` | `String` | SharePoint identifier of the site collection. | +| `item_id` | `String` | Identifier of the item this link points to. | +| `permission_id` | `String` | SharePoint permission identifier associated with this link. | +| `share_id` | `String` | Unique identifier of the sharing link. | +| `link_type` | `Enum8` | Access level granted by the link. Values: `VIEW`, `EDIT`, `EMBED`, `REVIEW`. | +| `link_url` | `String` | Full URL of the sharing link. | +| `link_scope` | `Enum8` | Audience the link is accessible to. Values: `ANONYMOUS` (anyone with the link), `ORGANIZATION` (anyone in the organization), `USERS` (specific users only). | +| `expires_on` | `DateTime` | Expiration timestamp of the link. A zero value indicates the link does not expire. | +| `is_password_protected` | `Bool` | `true` if the link requires a password to access. | +| `prevent_download` | `Bool` | `true` if the link prevents recipients from downloading the file. | + +**Primary key:** `(site_hostname, site_id, item_id, permission_id, share_id)` + +**Relations** + +| Related table | Join columns | Description | +|---|---|---| +| `sharepoint_online_objects` | `site_hostname`, `site_id`, `item_id` | The item this link provides access to. | +| `sharepoint_online_permissions` | `site_hostname`, `site_id`, `item_id`, `share_id` | Permissions granted through this link. | + +--- + +### sharepoint_online_sensitive_data + +Stores classification results from the sensitive data scan option. Each row represents one taxonomy term matched in a drive item. Multiple rows may exist for the same item when the item matches terms from multiple taxonomies. + +| Column | Type | Description | +|--------|------|-------------| +| `drive_id` | `String` | Microsoft Graph drive identifier of the document library that contains the item. | +| `drive_item_id` | `String` | Microsoft Graph drive item identifier of the classified file. | +| `taxonomy_name` | `String` | Name of the classification taxonomy (for example, `PII`, `Financial Records`). | +| `term_name` | `String` | Name of the specific classification term within the taxonomy (for example, `Credit Card Number`, `Social Security Number`). | +| `processing_time_seconds` | `Float32` | Time in seconds that the classification engine spent processing this item. | +| `classification_method` | `Nullable(Enum8)` | Optional. Method used to classify this item. Values: `SDK_AUTO` (automatic classification by the built-in engine), `SDK_CUSTOM` (classification using custom rules). | + +**Primary key:** `(drive_id, drive_item_id, taxonomy_name, term_name)` + +**Relations** + +| Related table | Join columns | Description | +|---|---|---| +| `sharepoint_online_objects` | `drive_id`, `drive_item_id` | The scanned item that produced these classification results. | + +--- + +## Views + +Access Analyzer creates views that simplify common queries. Use views in preference to querying base tables directly. + +| View | Base table | Description | +|------|------------|-------------| +| `sharepoint_online_objects_latest` | `sharepoint_online_objects` | Returns only the most recent version of each object record, deduplicated by `(site_hostname, site_id, item_id)`. | +| `sharepoint_online_permissions_latest` | `sharepoint_online_permissions` | Returns only the most recent version of each permission record, deduplicated by `(site_hostname, site_id, item_id, permission_id, principal_id)`. | +| `sharepoint_online_shared_links_latest` | `sharepoint_online_shared_links` | Returns only the most recent version of each sharing link record, deduplicated by `(site_hostname, site_id, item_id, permission_id, share_id)`. | +| `sharepoint_online_sensitive_data_latest` | `sharepoint_online_sensitive_data` | Returns one aggregated row per drive item, with `taxonomy_names` and `term_names` as arrays collecting all matched taxonomy and term names. Deduplicated by `(drive_id, drive_item_id)`. | diff --git a/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/set-up-source-group.md b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/set-up-source-group.md new file mode 100644 index 0000000000..b1c1d266c4 --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/set-up-source-group.md @@ -0,0 +1,49 @@ +--- +title: "Set Up SharePoint Online Source Group" +description: "Configure a SharePoint Online source group in Access Analyzer" +sidebar_position: 3 +--- + +# Set Up SharePoint Online Source Group + +**Step 1 –** Navigate to **Configuration** > **Source Groups** and click **Add Source**. The source group wizard opens. + +**Step 2 –** Select **SharePoint Online** and click **Next**. + +**Step 3 –** Enter a **Source Group Name**. + +**Step 4 –** Select a service account from the **Service Account** dropdown, or click **+** to create one inline. SharePoint Online requires a **Client ID and Certificate** service account type. See [Service Accounts](../../configurations/service-accounts/overview.md) for details. + +**Step 5 –** Enter the **Tenant ID** for your Microsoft Entra ID directory. This must be a valid UUID (for example, `550e8400-e29b-41d4-a716-446655440000`). + +**Step 6 –** Under **Certificate**, click **Generate and Download Certificate** to generate a certificate and download it to your machine. Upload this certificate to your registered Entra ID application before proceeding. See [Certificate Configuration](../../connectors/sharepoint-online/tenant-certificate-config.md) for upload steps. + +**Step 7 –** Click **Test Connection** to verify that Access Analyzer can authenticate to your SharePoint Online tenant. Resolve any failures before proceeding. + +**Step 8 –** Click **Next**. + +**Step 9 –** Under **Scanner Location**, select **System scanner** to run scans from the Access Analyzer service, or select **Custom scanner** to use a deployed scanner. See [Scanners](../../configurations/source-groups/scanners/overview.md) for details. + +**Step 10 –** Under **Scan Schedule**, select when to run the scan: + +- **Now** — Starts the scan immediately after setup completes. +- **At** — Runs the scan once at a specific date and time. +- **Advanced** — Runs the scan on a recurring schedule defined by a cron expression. + +**Step 11 –** Click **Complete Setup**. + +## What Happens Next + +Access Analyzer creates the source group and begins scanning your SharePoint Online environment. If you selected **Now**, the scan starts immediately. + +To check scan progress, navigate to **Configuration** > **Scan Executions**. + +To view results after the scan completes, see [Data Security Dashboard](../../dashboards-reports/data-security-dashboard/overview.md). + +## Edit a Source Group + +To modify an existing SharePoint Online source group, navigate to **Configuration** > **Source Groups**, select the source group, and click **Edit**. The wizard reopens with your current configuration pre-populated. You can update the source group name, service account, tenant ID, and scan schedule. + +:::note +Updating the service account replaces the certificate used to authenticate with SharePoint Online. Ensure the new service account's certificate is uploaded to your registered Entra ID application before saving. +::: diff --git a/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/sharepoint-online.md b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/sharepoint-online.md new file mode 100644 index 0000000000..347ee3f752 --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/sharepoint-online.md @@ -0,0 +1,33 @@ +--- +title: "SharePoint Online Scanning Overview" +description: "Overview of SharePoint Online scanning capabilities and prerequisites in Access Analyzer" +sidebar_position: 1 +--- + +# SharePoint Online Scanning Overview + +Access Analyzer scans SharePoint Online sites to map permissions, enumerate sharing links, and locate sensitive data across your tenant's document libraries and sites. It surfaces over-permissioned sites, anonymous and organization-wide sharing links, and files that contain sensitive content — giving security teams the information they need to reduce external exposure, enforce sharing policies, and meet cloud data governance requirements. + +## Prerequisites + +Before setting up a SharePoint Online source group, confirm that your environment meets the requirements below. The source group wizard connects to SharePoint Online over HTTPS using certificate-based authentication, so the Access Analyzer server must be able to reach the Microsoft identity platform and an app registration must be configured in your tenant. The certificate is generated by the wizard — you'll need the application's Client ID before you begin. + +### Service Account + +Access Analyzer uses a Client ID and Certificate service account to authenticate with SharePoint Online. Only the Client ID is entered when creating the service account — the certificate is generated automatically during source group setup when you click **Generate and Download Certificate**. You then upload the certificate to your registered Entra ID application before the connection can be tested. + +See [SharePoint Online Service Account](../../configurations/service-accounts/sharepoint-online.md) to create the service account and [SharePoint Online Connector Requirements](../../connectors/sharepoint-online/overview.md) for instructions on registering the application. + +### Network Requirements + +| Protocol | Port | Destination | +| --- | --- | --- | +| HTTPS | 443 | Microsoft identity platform (`login.microsoftonline.com`) | +| HTTPS | 443 | SharePoint Online (`yourtenant.sharepoint.com`) | + +### Before You Begin + +- A registered application in your Entra ID tenant. +- The application's **Tenant ID** and **Client ID**. +- A Client ID and Certificate service account created in Access Analyzer. +- Network connectivity from the Access Analyzer server to port 443 confirmed. diff --git a/docs/accessanalyzer/2601/gettingstarted/source-group-wizard.md b/docs/accessanalyzer/2601/gettingstarted/source-group-wizard.md deleted file mode 100644 index ece698c97b..0000000000 --- a/docs/accessanalyzer/2601/gettingstarted/source-group-wizard.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Source Group Wizard" -description: "How the Source Group Wizard guides you through connecting data sources and configuring scans" -sidebar_position: 10 ---- - -# Source Group Wizard - -*Content coming soon.* diff --git a/docs/accessanalyzer/2601/overview/overview.md b/docs/accessanalyzer/2601/overview/overview.md new file mode 100644 index 0000000000..2c2b36a077 --- /dev/null +++ b/docs/accessanalyzer/2601/overview/overview.md @@ -0,0 +1,100 @@ +--- +title: "Overview" +description: "Product overview and architecture of Netwrix Access Analyzer" +sidebar_position: 10 +--- + +# Overview + +## Product Overview + +Netwrix Access Analyzer is an on-premises Data Security Posture Management (DSPM) platform that helps security and compliance teams discover where sensitive data lives, who has access to it, and where access risks exist across their environment. + +Organizations face a persistent challenge: sensitive data accumulates across file servers, cloud platforms, and identity systems faster than security teams can track it. Permissions expand over time, inheritance gets broken, and stale data sits untouched for years — all without anyone knowing. Access Analyzer addresses this by scanning your data sources and identity providers continuously, classifying what it finds, and surfacing the results in dashboards and reports your team can act on. + +Access Analyzer connects to the following source types: + +- **File servers** — Scans SMB/CIFS file shares for permissions, folder-level ACLs, file ownership, and sensitive data content +- **SharePoint Online** — Scans SharePoint sites for permissions, sharing links, and sensitive data across document libraries +- **Active Directory** — Syncs users, groups, group memberships, and security risks from on-premises AD domains +- **Entra ID** — Syncs Microsoft Information Protection (MIP) sensitivity labels from your Microsoft 365 tenant + +After each scan, results are stored in a high-performance analytics database and made available through embedded Metabase dashboards and reports. Security teams can filter by domain, file server, site, or classification type, and drill into specific findings without writing queries. + +## Architecture Overview + +Access Analyzer runs entirely within your Kubernetes cluster. All components — the web application, API server, analytics database, and connector jobs — deploy to a single `access-analyzer` namespace. No data leaves your infrastructure. + +The platform uses a scan-as-job model: when a scan is triggered, the Connector API creates an ephemeral Kubernetes Job for the connector type (CIFS, SharePoint, Active Directory, or Entra ID). The job runs, connects to the external source, collects data, and streams results to the data ingestion service, which bulk-inserts them into ClickHouse. When the job completes, it posts a webhook back to the Core API to finalize the scan execution record. + +```mermaid +graph TB + Browser(["Browser"]) + + subgraph K8s["Kubernetes — access-analyzer namespace"] + Webapp["Web App\n(React)"] + CoreAPI["Core API\n(Rails + Sidekiq)"] + ConnAPI["Connector API\n(Go)"] + DI["Data Ingestion\n(Python)"] + MB["Metabase\n(Embedded Analytics)"] + + Redis[("Redis\nJob queue")] + PG[("PostgreSQL\nApp data")] + CH[("ClickHouse\nScan results")] + + subgraph Jobs["Connector Jobs — ephemeral Kubernetes Jobs"] + J1["CIFS Connector"] + J2["SharePoint Connector"] + J3["Active Directory Connector"] + J4["Entra ID Connector"] + end + end + + subgraph Ext["External Sources"] + FS["File Servers\nSMB · port 445"] + SP["SharePoint Online\nHTTPS · port 443"] + AD["Active Directory\nLDAP · port 389"] + EID["Entra ID\nHTTPS · port 443"] + end + + Browser -->|HTTPS| Webapp + Webapp -->|REST API| CoreAPI + Webapp -->|Embedded SDK + JWT SSO| MB + CoreAPI --> PG + CoreAPI --> Redis + CoreAPI -->|HTTP| ConnAPI + ConnAPI -->|Kubernetes Job API| Jobs + J1 -->|SMB| FS + J2 -->|Graph API| SP + J3 -->|LDAP| AD + J4 -->|Graph API| EID + J1 --> DI + J2 --> DI + J3 --> DI + J4 --> DI + DI -->|Bulk insert| CH + MB -->|JDBC| PG + MB -->|JDBC| CH +``` + +### Components + +**Web App** — React single-page application served from the cluster. Handles scan management, source configuration, results browsing, and embeds Metabase dashboards via the Metabase SDK using JWT-based single sign-on. + +**Core API** — Rails 8 application that exposes the REST API used by the web app. Manages application state in PostgreSQL, queues background jobs through Sidekiq and Redis, and coordinates scan execution by delegating to the Connector API. + +**Connector API** — Go service that translates scan requests from the Core API into Kubernetes Job definitions. It creates connector Jobs, monitors their completion, and posts results back to the Core API via webhook. + +**Connector Jobs** — Ephemeral Kubernetes Jobs that run the actual scan work. Each connector type (CIFS, SharePoint, Active Directory, Entra ID) is a containerized Python handler. Jobs connect directly to their target source, collect data, and stream rows to the Data Ingestion service in batches. Jobs are created on demand and cleaned up after completion. + +**Data Ingestion** — Python service that receives batched rows from connector jobs and bulk-inserts them into ClickHouse. Provides write isolation — connectors never write to ClickHouse directly. + +**Metabase** — Embedded analytics platform pre-configured with Access Analyzer dashboards and reports. Connects to both PostgreSQL and ClickHouse via JDBC. Users access Metabase through the web app with no separate login required. + +### Data Stores + +| Store | Purpose | +|-------|---------| +| **PostgreSQL** | Application data: users, sources, scans, scan executions, service accounts, configuration | +| **ClickHouse** | Scan results: file objects, permissions, ACLs, group memberships, sensitive data findings | +| **Redis** | Sidekiq job queue and session cache for the Core API | diff --git a/kb_allowlist.json b/kb_allowlist.json index 55782a0c91..1e5475e5a7 100644 --- a/kb_allowlist.json +++ b/kb_allowlist.json @@ -3,9 +3,9 @@ "current" ], "accessanalyzer": [ - "2601", "11.6", - "12.0" + "12.0", + "2601" ], "accessinformationcenter": [ "11.6", From d63a106bd6572a0e75894927e8c4554fdcf12ad0 Mon Sep 17 00:00:00 2001 From: Farrah Gamboa Date: Mon, 13 Apr 2026 10:17:00 -0400 Subject: [PATCH 11/62] AA26: Add source groups, scans, scan executions, and scanner best practices docs Documents source group management (create/edit/run/delete), scan configuration by connector type with concurrency guidance and scheduling, scan execution status definitions with aggregate logic, and scanner best practices for labeling, concurrency scaling, grouping strategy, and least-privilege naming. Generated with AI Co-Authored-By: Claude Code --- .../source-groups/scan-executions.md | 44 ++++++++- .../source-groups/scanners/best-practices.md | 55 ++++++++++- .../configurations/source-groups/scans.md | 54 +++++++++- .../source-groups/source-groups.md | 98 ++++++++++++++++++- 4 files changed, 244 insertions(+), 7 deletions(-) diff --git a/docs/accessanalyzer/2601/configurations/source-groups/scan-executions.md b/docs/accessanalyzer/2601/configurations/source-groups/scan-executions.md index 06fdfae6a1..25364459e3 100644 --- a/docs/accessanalyzer/2601/configurations/source-groups/scan-executions.md +++ b/docs/accessanalyzer/2601/configurations/source-groups/scan-executions.md @@ -1,9 +1,49 @@ --- title: "Scan Executions" -description: "Viewing scan execution history in the Configuration node" +description: "Understanding scan execution status and history in Access Analyzer" sidebar_position: 3 --- # Scan Executions -*Content coming soon.* +A scan execution is a single run of a scan at a specific point in time. Each time Access Analyzer runs a scan — whether triggered by a schedule or manually — it creates a new scan execution record. Execution history is retained per source so you can review past run outcomes. + +Scan executions are distinct from scan configurations. The [scan configuration](scans.md) defines what to collect and when. The scan execution records what happened during a specific run. + +## Execution status values + +| Status | Meaning | +| --- | --- | +| **Pending** | The execution is queued and waiting to start. This occurs when the Max Concurrent Scans limit is reached and additional executions are waiting their turn. | +| **Running** | The scanner is actively collecting data from the source. | +| **Pausing** | A pause was requested. The execution is finishing its current operation before pausing. | +| **Paused** | The execution has paused mid-run and can be resumed. | +| **Resuming** | A resume was requested. The execution is restarting from where it paused. | +| **Stopping** | A stop was requested. The execution is finishing its current operation before terminating. | +| **Post-processing** | Data collection is complete. Results are being processed and written to the database. | +| **Completed** | The execution finished successfully. | +| **Stopped** | The execution was manually stopped before completing. Partial results may have been collected. | +| **Cancelled** | The execution was cancelled before it started or early in the run. No results were collected. | +| **Failed** | The execution encountered an error and did not complete. Check the execution log for details. | + +## Source group scan status + +The source groups list displays an aggregate scan status for each group. This is computed from the most recent scan execution across all sources in the group, using the following priority order: + +1. **Paused** — One or more sources has a paused execution, and none are running. +2. **Running** — One or more sources has an execution in a pending, running, pausing, resuming, stopping, or post-processing state. +3. **Failed** — One or more sources has a failed execution, and none are running or paused. +4. **Completed** — All sources have completed their most recent execution successfully. +5. **Completed with errors** — One or more sources has a stopped or cancelled execution, and none meet the criteria above. +6. **Not run yet** — No scan executions exist for any source in the group. + +This means a group shows **Running** even if only one source is actively scanning, and it shows **Failed** only when no scans are still in progress. + +## Blocked operations during active executions + +Several operations are blocked while a source has an execution in an active state (pending, running, pausing, paused, resuming, stopping, or post-processing): + +- **Deleting a source group** — Stop all active scans before deleting the group. +- **Removing a source from a group** — Stop the source's active scan before removing it. + +Wait for the execution to reach a terminal state (completed, stopped, cancelled, or failed), or use the **Stop** action to terminate it, before proceeding with the blocked operation. diff --git a/docs/accessanalyzer/2601/configurations/source-groups/scanners/best-practices.md b/docs/accessanalyzer/2601/configurations/source-groups/scanners/best-practices.md index be4a4c9af6..333865cdf0 100644 --- a/docs/accessanalyzer/2601/configurations/source-groups/scanners/best-practices.md +++ b/docs/accessanalyzer/2601/configurations/source-groups/scanners/best-practices.md @@ -6,4 +6,57 @@ sidebar_position: 20 # Scanner Best Practices -*Content coming soon.* +## Use scanner labels to isolate scan traffic + +Scanner labels route scan executions to specific scanner pools. Use them to prevent scan traffic from one environment from sharing resources with another. + +Common labeling patterns: + +| Use Case | Example Label | +| --- | --- | +| Separate production and non-production scanning | `environment=production`, `environment=staging` | +| Route by geographic region | `region=us-east`, `region=eu-west` | +| Dedicate scanners to high-sensitivity source groups | `tier=restricted` | + +Define a labeling scheme before deploying scanners and apply it consistently. Labels applied to a source group are inherited by all scan executions in that group — you don't need to set them per source. + +## Set Max Concurrent Scans conservatively + +Start with the default value of 1 and increase only after validating that the target environment can handle parallel connections. + +Before increasing the limit: + +- Confirm the domain controller, file server, or other target can sustain simultaneous authenticated connections without degraded performance. +- Verify the network path between the scanner and the target has sufficient bandwidth for parallel data transfer. +- Consider the number of source groups that may run simultaneously — the limit is per group, and multiple groups can run at the same time. + +A safe approach is to increase the limit by 2–3 at a time and monitor scan completion times and target resource utilization before increasing further. + +## Group sources by environment and sensitivity + +Group sources that share the same operational profile — same environment (production vs. staging), same geographic location, and similar sensitivity level. Avoid mixing high-sensitivity and low-priority sources in a single group. + +This approach has two benefits: + +- It lets you assign different scanner pools and service accounts to different groups based on the security requirements of the environment. +- It makes aggregate scan status meaningful — a group that mixes critical and non-critical sources produces a status that doesn't clearly reflect the health of either. + +## Use least-privilege service accounts + +Each source group requires a service account for authentication. Assign an account that has only the permissions required for the connectors in that group. + +- Don't share a single service account across source groups that scan different environments. +- Don't reuse a service account between source groups with different sensitivity levels. +- Review service account permissions when adding new sources to an existing group — the account must have access to each new source. + +## Follow a consistent naming convention + +Source group names appear in the list view, in scan execution logs, and in any reporting that references the source. A consistent naming convention makes groups easier to identify and manage. + +A useful pattern: `--`. For example: + +- `ad-production-us-east` +- `fileserver-staging-eu-west` +- `sharepoint-production` + +Names are case-insensitive and must be unique across all source groups. Avoid names that embed credentials, IP addresses, or other values that change over time. diff --git a/docs/accessanalyzer/2601/configurations/source-groups/scans.md b/docs/accessanalyzer/2601/configurations/source-groups/scans.md index cbd6f26304..129f790e1d 100644 --- a/docs/accessanalyzer/2601/configurations/source-groups/scans.md +++ b/docs/accessanalyzer/2601/configurations/source-groups/scans.md @@ -1,9 +1,59 @@ --- title: "Scans" -description: "Managing scans in the Configuration node" +description: "Scan types, configuration, and scheduling in Access Analyzer source groups" sidebar_position: 2 --- # Scans -*Content coming soon.* +A scan defines what Access Analyzer collects from a source and how often it runs. Each source in a group can have one or more scans, one per scan type. Scans are persistent configurations — each run of a scan produces a [scan execution](scan-executions.md). + +## Scan types + +| Scan Type | What it collects | +| --- | --- | +| **Access Scan** | Permissions, group memberships, and access rights across the data source. | +| **Sensitive Data Scan** | Files or objects that contain sensitive content, based on the classification policies configured under **Configuration** > **Sensitive Data**. | + +A source group can be configured with one or both scan types. The scan types available depend on the connector: + +| Source Type | Access Scan | Sensitive Data Scan | +| --- | --- | --- | +| Active Directory | Yes | No | +| File Server | Yes | Yes | +| Entra ID | Yes | No | +| SharePoint Online | Yes | Yes | + +## Scan configuration + +When you create a source group, the setup wizard collects scan parameters and creates scan configurations that apply to all sources added to the group. Each scan configuration includes: + +- **Scan type** — Access Scan, Sensitive Data Scan, or both. +- **Schedule** — A cron expression that controls when the scan runs automatically. Leave the schedule empty to run scans manually only. +- **Scan parameters** — Source-type-specific settings such as scope, depth, and included paths. These vary by connector. + +Individual sources can override the group-level scan configuration if their requirements differ from the group default. + +## Max concurrent scans + +The **Max Concurrent Scans** setting on a source group controls how many sources in that group can scan simultaneously. When a group-level scan run is triggered, Access Analyzer queues executions for all sources and processes them in batches up to the configured limit. + +| Value | Effect | +| --- | --- | +| **1** (default) | Sources scan one at a time. Lowest resource impact; longest total run time for large groups. | +| **2–10** | Moderate parallelism. Suitable for most environments. | +| **11–30** | High parallelism. Use only when target infrastructure and network bandwidth can support it. | + +The default value of 1 is intentionally conservative. Increase it only after confirming the target environment and network can sustain parallel connections without performance degradation. + +:::note +The Max Concurrent Scans limit applies within a single source group. It does not limit scan activity across multiple source groups running simultaneously. +::: + +## Schedules + +Scans run on a cron schedule that you set during source group creation. The schedule is stored per scan configuration, not per source — all sources in the group run on the same schedule by default. + +To modify the schedule for a source group's scans, edit the group and update the schedule field. + +Sources with no schedule configured will not run automatically. Run them manually from the source groups list using the **Run** action. diff --git a/docs/accessanalyzer/2601/configurations/source-groups/source-groups.md b/docs/accessanalyzer/2601/configurations/source-groups/source-groups.md index 1ee2b78421..5c44507250 100644 --- a/docs/accessanalyzer/2601/configurations/source-groups/source-groups.md +++ b/docs/accessanalyzer/2601/configurations/source-groups/source-groups.md @@ -1,9 +1,103 @@ --- title: "Source Groups" -description: "Managing source groups in the Configuration node" +description: "Managing source groups in Access Analyzer — create, configure, and operate groups of data sources" sidebar_position: 1 --- # Source Groups -*Content coming soon.* +A source group is a named container that organizes data sources of the same type for coordinated scanning. All sources in a group share a service account and a concurrency limit, and you can run or stop scans across all sources in the group with a single action. + +Navigate to **Configuration** > **Source Groups** to view, create, and manage source groups. + +## Source groups list + +The source groups list displays all configured source groups. Each row shows: + +| Column | Description | +| --- | --- | +| **Name** | The source group name. | +| **Source Type** | The type of data source in the group (Active Directory, File Server, Entra ID, or SharePoint Online). | +| **Service Account** | The service account used to authenticate scans in this group. | +| **Status** | Whether the group is **Active** or **Inactive**. Inactive groups are excluded from scheduled scan runs. | +| **Scan Types** | The scan types configured for this group (Access Scan, Sensitive Data Scan, or both). | +| **Scanner Labels** | Key-value labels used to route scans to specific scanner pools. Displayed only for Active Directory and File Server groups. | +| **Last Scan** | The timestamp of the most recent completed scan execution across all sources in the group. | + +Use the search field to filter by name. You can sort by any column and filter by source type, status, service account, or scan status. + +## Create a source group + +1. Click **Add Source Group**. +2. Enter a **Name** and optional **Description**. Names must be unique (case-insensitive) and between 1 and 255 characters. +3. Select the **Source Type**. This value is permanent — it can't be changed after the group is created. +4. Select or create a **Service Account**. The wizard filters available accounts to those compatible with the selected source type. To create a new account inline, click **+** next to the field. +5. Set **Max Concurrent Scans**. This controls how many sources within the group can scan simultaneously. The default is 1. See [Scans](scans.md) for guidance on choosing a value. +6. For Active Directory and File Server groups, optionally add **Scanner Labels** to route scans to a specific scanner pool. See [Scanners](scanners/overview.md). +7. Add sources and configure scan parameters. You can also add sources later from the group detail view. +8. Click **Save**. + +:::warning +Changing the source type is not possible after a source group is created. If you need a different source type, create a new source group and delete the original. +::: + +## Edit a source group + +1. In the source groups list, click the actions menu for a group and select **Edit**. +2. Modify any of the following fields: + - Name and description + - Service account + - Max concurrent scans + - Scanner labels + - Status (Active or Inactive) +3. Click **Save**. + +The source type cannot be changed. If you update the service account, the new credentials apply to all future scans in the group — verify the replacement account has the required permissions before saving. + +## Add sources to a group + +1. In the source groups list, click the actions menu for a group and select **View Sources**. +2. Click **Add Source**. +3. Complete the source configuration form. Required fields vary by source type. +4. Click **Save**. + +Sources you add inherit the group's service account and scan configuration unless you override them at the source level. + +## Remove sources from a group + +1. In the source groups list, click the actions menu for a group and select **View Sources**. +2. In the sources drawer, click the actions menu for a source and select **Remove**. + +You can't remove a source that has a scan in a pending, running, pausing, paused, resuming, stopping, or post-processing state. Wait for the scan to complete or stop it first. + +## Run scans + +To start scans across all sources in a group, click the **Run** button in the actions menu for the group. Access Analyzer queues scan executions for every configured scan in the group, subject to the **Max Concurrent Scans** limit. + +To run scans for a single source, open the source from the **View Sources** drawer and use the source-level run action. + +## Stop scans + +To stop all running and pending scans in a group, click **Stop** in the actions menu. Access Analyzer sends a stop signal to every active scan execution in the group. Scans in a stopping or post-processing state continue until they reach a terminal state. + +## Delete a source group + +1. In the source groups list, click the actions menu for a group and select **Delete**. +2. Confirm the deletion. + +:::warning +Deleting a source group permanently deletes all sources it contains. This action can't be undone. +::: + +You can't delete a source group while any of its scans are in a pending, running, pausing, paused, resuming, stopping, or post-processing state. Stop all active scans before deleting. + +## Constraints + +| Setting | Constraint | +| --- | --- | +| **Name** | 1–255 characters; must be unique (case-insensitive) across all source groups | +| **Description** | Maximum 10,000 characters | +| **Source type** | Set at creation; can't be changed afterward | +| **Max concurrent scans** | 1–30; default is 1 | +| **Delete** | Blocked while any source has an active scan execution | +| **Remove source** | Blocked while that source has an active scan execution | From 5e183ecd9f3806ba7bffd427986c094a20ffe93a Mon Sep 17 00:00:00 2001 From: Farrah Gamboa Date: Mon, 13 Apr 2026 10:43:24 -0400 Subject: [PATCH 12/62] AA26: Rename service account pages to credential type names Replace entra-id.md and sharepoint-online.md with client-id-secret.md and client-id-certificate.md so sidebar titles match the credential type labels shown in the application UI. Data source context is in the article body. Update cross-references and overview table to match. Generated with AI Co-Authored-By: Claude Code --- .../{sharepoint-online.md => client-id-certificate.md} | 10 ++++++---- .../{entra-id.md => client-id-secret.md} | 10 ++++++---- .../2601/configurations/service-accounts/overview.md | 4 ++-- .../2601/gettingstarted/entra-id/entra-id.md | 2 +- .../sharepoint-online/sharepoint-online.md | 2 +- 5 files changed, 16 insertions(+), 12 deletions(-) rename docs/accessanalyzer/2601/configurations/service-accounts/{sharepoint-online.md => client-id-certificate.md} (69%) rename docs/accessanalyzer/2601/configurations/service-accounts/{entra-id.md => client-id-secret.md} (65%) diff --git a/docs/accessanalyzer/2601/configurations/service-accounts/sharepoint-online.md b/docs/accessanalyzer/2601/configurations/service-accounts/client-id-certificate.md similarity index 69% rename from docs/accessanalyzer/2601/configurations/service-accounts/sharepoint-online.md rename to docs/accessanalyzer/2601/configurations/service-accounts/client-id-certificate.md index d9db342fe0..5432b3cea7 100644 --- a/docs/accessanalyzer/2601/configurations/service-accounts/sharepoint-online.md +++ b/docs/accessanalyzer/2601/configurations/service-accounts/client-id-certificate.md @@ -1,12 +1,14 @@ --- -title: "SharePoint Online Service Account" -description: "Client ID and certificate service accounts for SharePoint Online source groups" +title: "Client ID/Certificate" +description: "Client ID and certificate credentials for SharePoint Online source groups" sidebar_position: 4 --- -# SharePoint Online Service Account +# Client ID/Certificate -SharePoint Online source groups use the Client ID and Certificate credential type to authenticate with SharePoint Online using certificate-based authentication. This requires a registered application in your Entra ID tenant. The certificate is generated by the source group wizard — you don't create or upload it here. +The Client ID/Certificate credential type authenticates with SharePoint Online using certificate-based authentication. Use this credential type when configuring SharePoint Online source groups. + +This requires a registered application in your Entra ID tenant. The certificate is generated by the source group wizard — you don't create or upload it here. ## Fields diff --git a/docs/accessanalyzer/2601/configurations/service-accounts/entra-id.md b/docs/accessanalyzer/2601/configurations/service-accounts/client-id-secret.md similarity index 65% rename from docs/accessanalyzer/2601/configurations/service-accounts/entra-id.md rename to docs/accessanalyzer/2601/configurations/service-accounts/client-id-secret.md index e62de9a69e..dec30056c0 100644 --- a/docs/accessanalyzer/2601/configurations/service-accounts/entra-id.md +++ b/docs/accessanalyzer/2601/configurations/service-accounts/client-id-secret.md @@ -1,12 +1,14 @@ --- -title: "Entra ID Service Account" -description: "Client ID and secret service accounts for Entra ID source groups" +title: "Client ID/Secret" +description: "Client ID and secret credentials for Entra ID source groups" sidebar_position: 3 --- -# Entra ID Service Account +# Client ID/Secret -Entra ID source groups use the Client ID and Secret credential type to authenticate with Microsoft Entra ID via the Microsoft Graph API. This requires a registered application in your Entra ID tenant with the appropriate API permissions granted. +The Client ID/Secret credential type authenticates with Microsoft Entra ID via the Microsoft Graph API. Use this credential type when configuring Entra ID source groups. + +This requires a registered application in your Entra ID tenant with the appropriate API permissions granted. ## Fields diff --git a/docs/accessanalyzer/2601/configurations/service-accounts/overview.md b/docs/accessanalyzer/2601/configurations/service-accounts/overview.md index d3d151b21e..14be172d1f 100644 --- a/docs/accessanalyzer/2601/configurations/service-accounts/overview.md +++ b/docs/accessanalyzer/2601/configurations/service-accounts/overview.md @@ -19,8 +19,8 @@ You can create a service account in two ways: | --- | --- | | Active Directory | Username and Password | | File Server | Username and Password | -| Entra ID | Client ID and Secret | -| SharePoint Online | Client ID and Certificate | +| Entra ID | Client ID/Secret | +| SharePoint Online | Client ID/Certificate | ## Editing Service Accounts diff --git a/docs/accessanalyzer/2601/gettingstarted/entra-id/entra-id.md b/docs/accessanalyzer/2601/gettingstarted/entra-id/entra-id.md index 9465add534..de8b12d52f 100644 --- a/docs/accessanalyzer/2601/gettingstarted/entra-id/entra-id.md +++ b/docs/accessanalyzer/2601/gettingstarted/entra-id/entra-id.md @@ -16,7 +16,7 @@ Before setting up an Entra ID source group, confirm that your environment meets Access Analyzer uses a Client ID and Secret service account to authenticate with Microsoft Entra ID via the Microsoft Graph API. This requires a registered application in your Entra ID tenant with the appropriate API permissions granted and a client secret generated for that application. -See [Entra ID Service Account](../../configurations/service-accounts/entra-id.md) to create the service account and [Entra ID Requirements](../../connectors/entra-id/overview.md) for instructions on registering the application and granting the required permissions. +See [Client ID/Secret service account](../../configurations/service-accounts/client-id-secret.md) to create the service account and [Entra ID Requirements](../../connectors/entra-id/overview.md) for instructions on registering the application and granting the required permissions. ### Network Requirements diff --git a/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/sharepoint-online.md b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/sharepoint-online.md index 347ee3f752..985b4dc651 100644 --- a/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/sharepoint-online.md +++ b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/sharepoint-online.md @@ -16,7 +16,7 @@ Before setting up a SharePoint Online source group, confirm that your environmen Access Analyzer uses a Client ID and Certificate service account to authenticate with SharePoint Online. Only the Client ID is entered when creating the service account — the certificate is generated automatically during source group setup when you click **Generate and Download Certificate**. You then upload the certificate to your registered Entra ID application before the connection can be tested. -See [SharePoint Online Service Account](../../configurations/service-accounts/sharepoint-online.md) to create the service account and [SharePoint Online Connector Requirements](../../connectors/sharepoint-online/overview.md) for instructions on registering the application. +See [Client ID/Certificate service account](../../configurations/service-accounts/client-id-certificate.md) to create the service account and [SharePoint Online Connector Requirements](../../connectors/sharepoint-online/overview.md) for instructions on registering the application. ### Network Requirements From 4a4d062e12917d778bafe8211a2ddc574c6951d1 Mon Sep 17 00:00:00 2001 From: carlos-mejia_nwx Date: Thu, 19 Mar 2026 20:13:29 -0400 Subject: [PATCH 13/62] AA26: Add Access Analyzer v1.0 documentation (266 pages, outline WIP) Co-Authored-By: Claude Opus 4.6 --- .../1.0/activitymonitoring/_category_.json | 10 ++ .../configuration/_category_.json | 10 ++ .../configuration/batchprocessing.md | 8 + .../configuration/connectingnam.md | 8 + .../configuration/enablingsyslog.md | 8 + .../1.0/activitymonitoring/overview.md | 8 + .../viewingdata/_category_.json | 10 ++ .../viewingdata/fileaccessevents.md | 8 + .../viewingdata/useractivitypatterns.md | 8 + docs/accessanalyzer/1.0/admin/_category_.json | 10 ++ .../1.0/admin/auditlogs/_category_.json | 10 ++ .../1.0/admin/auditlogs/export.md | 43 +++++ .../1.0/admin/auditlogs/overview.md | 39 +++++ .../1.0/admin/authentication/_category_.json | 10 ++ .../1.0/admin/authentication/overview.md | 34 ++++ .../admin/authentication/sessionmonitoring.md | 38 +++++ .../1.0/admin/authentication/tokenrefresh.md | 34 ++++ .../1.0/admin/iam/_category_.json | 10 ++ .../1.0/admin/iam/identitiesentitlements.md | 36 +++++ .../1.0/admin/iam/identitysync.md | 43 +++++ docs/accessanalyzer/1.0/admin/iam/overview.md | 32 ++++ .../1.0/admin/iam/permissionpaths.md | 39 +++++ .../1.0/admin/navigate/_category_.json | 10 ++ .../1.0/admin/navigate/datatables.md | 35 ++++ .../1.0/admin/navigate/overview.md | 27 ++++ .../1.0/admin/navigate/sidebar.md | 34 ++++ docs/accessanalyzer/1.0/admin/overview.md | 29 ++++ .../1.0/admin/scans/_category_.json | 10 ++ .../1.0/admin/scans/executionhistory.md | 44 +++++ .../1.0/admin/scans/overview.md | 31 ++++ .../1.0/admin/scans/runningstop.md | 42 +++++ .../1.0/admin/scans/scantypes.md | 64 ++++++++ .../1.0/admin/scans/scheduling.md | 50 ++++++ .../1.0/admin/sensitivedata/_category_.json | 10 ++ .../sensitivedata/customclassification.md | 44 +++++ .../1.0/admin/sensitivedata/overview.md | 34 ++++ .../1.0/admin/sensitivedata/patterngroups.md | 43 +++++ .../1.0/admin/sensitivedata/taxonomygroups.md | 39 +++++ .../1.0/admin/serviceaccounts/_category_.json | 10 ++ .../1.0/admin/serviceaccounts/associating.md | 42 +++++ .../admin/serviceaccounts/credentialtypes.md | 37 +++++ .../1.0/admin/serviceaccounts/overview.md | 33 ++++ .../1.0/admin/settings/_category_.json | 10 ++ .../1.0/admin/settings/featureflags.md | 48 ++++++ .../1.0/admin/settings/overview.md | 33 ++++ .../1.0/admin/settings/scanlimits.md | 37 +++++ .../1.0/admin/settings/sessionttl.md | 41 +++++ .../1.0/admin/sources/_category_.json | 10 ++ .../1.0/admin/sources/editdelete.md | 40 +++++ .../1.0/admin/sources/overview.md | 42 +++++ .../1.0/admin/sources/sourcegroups.md | 51 ++++++ .../1.0/admin/sources/sourcetypes.md | 35 ++++ .../1.0/admin/sources/testconnections.md | 54 +++++++ docs/accessanalyzer/1.0/admin/systemlogs.md | 47 ++++++ .../1.0/admin/users/_category_.json | 10 ++ .../1.0/admin/users/overview.md | 38 +++++ docs/accessanalyzer/1.0/admin/users/roles.md | 36 +++++ .../1.0/admin/users/sessions.md | 35 ++++ .../1.0/connectors/_category_.json | 10 ++ .../1.0/connectors/iam/_category_.json | 10 ++ .../iam/activedirectory/_category_.json | 10 ++ .../iam/activedirectory/connectionsetup.md | 47 ++++++ .../iam/activedirectory/customattributes.md | 12 ++ .../iam/activedirectory/groupmembership.md | 26 +++ .../iam/activedirectory/usergroupsync.md | 30 ++++ .../connectors/iam/entraid/_category_.json | 10 ++ .../connectors/iam/entraid/appregistration.md | 74 +++++++++ .../connectors/iam/entraid/certificateauth.md | 12 ++ .../connectors/iam/entraid/usergroupsync.md | 47 ++++++ .../iam/localgroups/_category_.json | 10 ++ .../iam/localgroups/powershellsetup.md | 52 ++++++ .../iam/localgroups/usergroupcollection.md | 40 +++++ .../1.0/connectors/iam/overview.md | 21 +++ .../accessanalyzer/1.0/connectors/overview.md | 42 +++++ .../1.0/connectors/source/_category_.json | 10 ++ .../connectors/source/cifs/_category_.json | 10 ++ .../source/cifs/connectionconfig.md | 79 +++++++++ .../source/cifs/filevssharelevel.md | 53 +++++++ .../connectors/source/cifs/ntfspermissions.md | 33 ++++ .../source/cifs/scandepthworkers.md | 54 +++++++ .../source/cifs/shareenumeration.md | 53 +++++++ .../1.0/connectors/source/overview.md | 23 +++ .../source/sharepointonline/_category_.json | 10 ++ .../sharepointonline/connectionconfig.md | 44 +++++ .../permissionsharinglinks.md | 35 ++++ .../sharepointonline/scanningspecificsites.md | 30 ++++ .../sharepointonline/sitelibraryenum.md | 29 ++++ .../1.0/dashboards/_category_.json | 10 ++ .../1.0/dashboards/activedirectory.md | 8 + .../1.0/dashboards/copilotreadiness.md | 8 + .../1.0/dashboards/datasecurity.md | 8 + docs/accessanalyzer/1.0/dashboards/entraid.md | 8 + .../1.0/dashboards/metabase/_category_.json | 10 ++ .../dashboards/metabase/accessingreports.md | 36 +++++ .../1.0/dashboards/metabase/exportingdata.md | 41 +++++ .../1.0/dashboards/metabase/savedreports.md | 38 +++++ .../accessanalyzer/1.0/dashboards/overview.md | 33 ++++ .../1.0/gettingstarted/_category_.json | 10 ++ .../gettingstarted/dashboardwalkthrough.md | 44 +++++ .../1.0/gettingstarted/firstlogin.md | 52 ++++++ .../gettingstarted/firstscan/_category_.json | 10 ++ .../gettingstarted/firstscan/addingsource.md | 70 ++++++++ .../firstscan/configuringscan.md | 94 +++++++++++ .../1.0/gettingstarted/firstscan/overview.md | 28 ++++ .../gettingstarted/firstscan/runningscan.md | 56 +++++++ .../firstscan/viewingresults.md | 49 ++++++ .../1.0/gettingstarted/overview.md | 26 +++ docs/accessanalyzer/1.0/index.md | 30 ++++ .../1.0/install/_category_.json | 6 + docs/accessanalyzer/1.0/install/dspmctl.md | 141 ++++++++++++++++ .../1.0/install/environmentvariables.md | 92 +++++++++++ docs/accessanalyzer/1.0/install/network.md | 96 +++++++++++ docs/accessanalyzer/1.0/install/overview.md | 49 ++++++ .../accessanalyzer/1.0/install/postinstall.md | 97 +++++++++++ docs/accessanalyzer/1.0/install/preflight.md | 111 +++++++++++++ .../1.0/install/quickinstall.md | 128 +++++++++++++++ .../1.0/install/requirements.md | 104 ++++++++++++ docs/accessanalyzer/1.0/install/security.md | 65 ++++++++ docs/accessanalyzer/1.0/install/ssl.md | 56 +++++++ docs/accessanalyzer/1.0/install/stepbystep.md | 150 ++++++++++++++++++ docs/accessanalyzer/1.0/install/uninstall.md | 52 ++++++ docs/accessanalyzer/1.0/install/upgrade.md | 77 +++++++++ .../1.0/overview/_category_.json | 10 ++ .../1.0/overview/architecture.md | 69 ++++++++ .../1.0/overview/keyconcepts.md | 87 ++++++++++ docs/accessanalyzer/1.0/overview/overview.md | 36 +++++ .../1.0/requirements/_category_.json | 10 ++ .../requirements/connectors/_category_.json | 10 ++ .../connectors/activedirectory.md | 45 ++++++ .../1.0/requirements/connectors/cifs.md | 52 ++++++ .../1.0/requirements/connectors/entraid.md | 54 +++++++ .../requirements/connectors/localgroups.md | 52 ++++++ .../connectors/sharepointonline.md | 57 +++++++ .../1.0/requirements/database/_category_.json | 10 ++ .../1.0/requirements/database/clickhouse.md | 30 ++++ .../1.0/requirements/database/postgresql.md | 40 +++++ .../1.0/requirements/database/redis.md | 43 +++++ .../1.0/requirements/overview.md | 35 ++++ .../1.0/requirements/system/_category_.json | 10 ++ .../1.0/requirements/system/hardware.md | 84 ++++++++++ .../1.0/requirements/system/kubernetes.md | 53 +++++++ .../1.0/requirements/system/network.md | 64 ++++++++ .../sensitivedatadiscovery/_category_.json | 10 ++ .../1.0/sensitivedatadiscovery/overview.md | 32 ++++ .../patterns/_category_.json | 10 ++ .../patterns/builtinpatterns.md | 34 ++++ .../patterns/custompatterns.md | 47 ++++++ .../patterns/patterngroups.md | 39 +++++ .../reviewingresults/_category_.json | 10 ++ .../classificationbreakdown.md | 43 +++++ .../reviewingresults/matchcounts.md | 46 ++++++ .../1.0/sensitivedatadiscovery/runningscan.md | 43 +++++ .../taxonomy/_category_.json | 10 ++ .../taxonomy/autovscustom.md | 41 +++++ .../taxonomy/classificationrules.md | 40 +++++ .../taxonomy/taxonomygroups.md | 42 +++++ .../1.0/troubleshooting/_category_.json | 10 ++ .../commonissues/_category_.json | 10 ++ .../commonissues/connectionfailures.md | 61 +++++++ .../commonissues/databaseconnectivity.md | 97 +++++++++++ .../commonissues/scanerrors.md | 61 +++++++ .../healthchecks/_category_.json | 10 ++ .../troubleshooting/healthchecks/endpoints.md | 49 ++++++ .../troubleshooting/healthchecks/probes.md | 55 +++++++ .../jobmonitoring/_category_.json | 10 ++ .../jobmonitoring/failedjobs.md | 58 +++++++ .../troubleshooting/jobmonitoring/queues.md | 52 ++++++ .../troubleshooting/jobmonitoring/sidekiq.md | 50 ++++++ .../observability/_category_.json | 10 ++ .../observability/opentelemetry.md | 76 +++++++++ .../observability/prometheus.md | 70 ++++++++ .../1.0/troubleshooting/overview.md | 70 ++++++++ kb_allowlist.json | 1 + sidebars/accessanalyzer/1.0.js | 8 + src/config/products.js | 6 + 175 files changed, 6562 insertions(+) create mode 100644 docs/accessanalyzer/1.0/activitymonitoring/_category_.json create mode 100644 docs/accessanalyzer/1.0/activitymonitoring/configuration/_category_.json create mode 100644 docs/accessanalyzer/1.0/activitymonitoring/configuration/batchprocessing.md create mode 100644 docs/accessanalyzer/1.0/activitymonitoring/configuration/connectingnam.md create mode 100644 docs/accessanalyzer/1.0/activitymonitoring/configuration/enablingsyslog.md create mode 100644 docs/accessanalyzer/1.0/activitymonitoring/overview.md create mode 100644 docs/accessanalyzer/1.0/activitymonitoring/viewingdata/_category_.json create mode 100644 docs/accessanalyzer/1.0/activitymonitoring/viewingdata/fileaccessevents.md create mode 100644 docs/accessanalyzer/1.0/activitymonitoring/viewingdata/useractivitypatterns.md create mode 100644 docs/accessanalyzer/1.0/admin/_category_.json create mode 100644 docs/accessanalyzer/1.0/admin/auditlogs/_category_.json create mode 100644 docs/accessanalyzer/1.0/admin/auditlogs/export.md create mode 100644 docs/accessanalyzer/1.0/admin/auditlogs/overview.md create mode 100644 docs/accessanalyzer/1.0/admin/authentication/_category_.json create mode 100644 docs/accessanalyzer/1.0/admin/authentication/overview.md create mode 100644 docs/accessanalyzer/1.0/admin/authentication/sessionmonitoring.md create mode 100644 docs/accessanalyzer/1.0/admin/authentication/tokenrefresh.md create mode 100644 docs/accessanalyzer/1.0/admin/iam/_category_.json create mode 100644 docs/accessanalyzer/1.0/admin/iam/identitiesentitlements.md create mode 100644 docs/accessanalyzer/1.0/admin/iam/identitysync.md create mode 100644 docs/accessanalyzer/1.0/admin/iam/overview.md create mode 100644 docs/accessanalyzer/1.0/admin/iam/permissionpaths.md create mode 100644 docs/accessanalyzer/1.0/admin/navigate/_category_.json create mode 100644 docs/accessanalyzer/1.0/admin/navigate/datatables.md create mode 100644 docs/accessanalyzer/1.0/admin/navigate/overview.md create mode 100644 docs/accessanalyzer/1.0/admin/navigate/sidebar.md create mode 100644 docs/accessanalyzer/1.0/admin/overview.md create mode 100644 docs/accessanalyzer/1.0/admin/scans/_category_.json create mode 100644 docs/accessanalyzer/1.0/admin/scans/executionhistory.md create mode 100644 docs/accessanalyzer/1.0/admin/scans/overview.md create mode 100644 docs/accessanalyzer/1.0/admin/scans/runningstop.md create mode 100644 docs/accessanalyzer/1.0/admin/scans/scantypes.md create mode 100644 docs/accessanalyzer/1.0/admin/scans/scheduling.md create mode 100644 docs/accessanalyzer/1.0/admin/sensitivedata/_category_.json create mode 100644 docs/accessanalyzer/1.0/admin/sensitivedata/customclassification.md create mode 100644 docs/accessanalyzer/1.0/admin/sensitivedata/overview.md create mode 100644 docs/accessanalyzer/1.0/admin/sensitivedata/patterngroups.md create mode 100644 docs/accessanalyzer/1.0/admin/sensitivedata/taxonomygroups.md create mode 100644 docs/accessanalyzer/1.0/admin/serviceaccounts/_category_.json create mode 100644 docs/accessanalyzer/1.0/admin/serviceaccounts/associating.md create mode 100644 docs/accessanalyzer/1.0/admin/serviceaccounts/credentialtypes.md create mode 100644 docs/accessanalyzer/1.0/admin/serviceaccounts/overview.md create mode 100644 docs/accessanalyzer/1.0/admin/settings/_category_.json create mode 100644 docs/accessanalyzer/1.0/admin/settings/featureflags.md create mode 100644 docs/accessanalyzer/1.0/admin/settings/overview.md create mode 100644 docs/accessanalyzer/1.0/admin/settings/scanlimits.md create mode 100644 docs/accessanalyzer/1.0/admin/settings/sessionttl.md create mode 100644 docs/accessanalyzer/1.0/admin/sources/_category_.json create mode 100644 docs/accessanalyzer/1.0/admin/sources/editdelete.md create mode 100644 docs/accessanalyzer/1.0/admin/sources/overview.md create mode 100644 docs/accessanalyzer/1.0/admin/sources/sourcegroups.md create mode 100644 docs/accessanalyzer/1.0/admin/sources/sourcetypes.md create mode 100644 docs/accessanalyzer/1.0/admin/sources/testconnections.md create mode 100644 docs/accessanalyzer/1.0/admin/systemlogs.md create mode 100644 docs/accessanalyzer/1.0/admin/users/_category_.json create mode 100644 docs/accessanalyzer/1.0/admin/users/overview.md create mode 100644 docs/accessanalyzer/1.0/admin/users/roles.md create mode 100644 docs/accessanalyzer/1.0/admin/users/sessions.md create mode 100644 docs/accessanalyzer/1.0/connectors/_category_.json create mode 100644 docs/accessanalyzer/1.0/connectors/iam/_category_.json create mode 100644 docs/accessanalyzer/1.0/connectors/iam/activedirectory/_category_.json create mode 100644 docs/accessanalyzer/1.0/connectors/iam/activedirectory/connectionsetup.md create mode 100644 docs/accessanalyzer/1.0/connectors/iam/activedirectory/customattributes.md create mode 100644 docs/accessanalyzer/1.0/connectors/iam/activedirectory/groupmembership.md create mode 100644 docs/accessanalyzer/1.0/connectors/iam/activedirectory/usergroupsync.md create mode 100644 docs/accessanalyzer/1.0/connectors/iam/entraid/_category_.json create mode 100644 docs/accessanalyzer/1.0/connectors/iam/entraid/appregistration.md create mode 100644 docs/accessanalyzer/1.0/connectors/iam/entraid/certificateauth.md create mode 100644 docs/accessanalyzer/1.0/connectors/iam/entraid/usergroupsync.md create mode 100644 docs/accessanalyzer/1.0/connectors/iam/localgroups/_category_.json create mode 100644 docs/accessanalyzer/1.0/connectors/iam/localgroups/powershellsetup.md create mode 100644 docs/accessanalyzer/1.0/connectors/iam/localgroups/usergroupcollection.md create mode 100644 docs/accessanalyzer/1.0/connectors/iam/overview.md create mode 100644 docs/accessanalyzer/1.0/connectors/overview.md create mode 100644 docs/accessanalyzer/1.0/connectors/source/_category_.json create mode 100644 docs/accessanalyzer/1.0/connectors/source/cifs/_category_.json create mode 100644 docs/accessanalyzer/1.0/connectors/source/cifs/connectionconfig.md create mode 100644 docs/accessanalyzer/1.0/connectors/source/cifs/filevssharelevel.md create mode 100644 docs/accessanalyzer/1.0/connectors/source/cifs/ntfspermissions.md create mode 100644 docs/accessanalyzer/1.0/connectors/source/cifs/scandepthworkers.md create mode 100644 docs/accessanalyzer/1.0/connectors/source/cifs/shareenumeration.md create mode 100644 docs/accessanalyzer/1.0/connectors/source/overview.md create mode 100644 docs/accessanalyzer/1.0/connectors/source/sharepointonline/_category_.json create mode 100644 docs/accessanalyzer/1.0/connectors/source/sharepointonline/connectionconfig.md create mode 100644 docs/accessanalyzer/1.0/connectors/source/sharepointonline/permissionsharinglinks.md create mode 100644 docs/accessanalyzer/1.0/connectors/source/sharepointonline/scanningspecificsites.md create mode 100644 docs/accessanalyzer/1.0/connectors/source/sharepointonline/sitelibraryenum.md create mode 100644 docs/accessanalyzer/1.0/dashboards/_category_.json create mode 100644 docs/accessanalyzer/1.0/dashboards/activedirectory.md create mode 100644 docs/accessanalyzer/1.0/dashboards/copilotreadiness.md create mode 100644 docs/accessanalyzer/1.0/dashboards/datasecurity.md create mode 100644 docs/accessanalyzer/1.0/dashboards/entraid.md create mode 100644 docs/accessanalyzer/1.0/dashboards/metabase/_category_.json create mode 100644 docs/accessanalyzer/1.0/dashboards/metabase/accessingreports.md create mode 100644 docs/accessanalyzer/1.0/dashboards/metabase/exportingdata.md create mode 100644 docs/accessanalyzer/1.0/dashboards/metabase/savedreports.md create mode 100644 docs/accessanalyzer/1.0/dashboards/overview.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/_category_.json create mode 100644 docs/accessanalyzer/1.0/gettingstarted/dashboardwalkthrough.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/firstlogin.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/firstscan/_category_.json create mode 100644 docs/accessanalyzer/1.0/gettingstarted/firstscan/addingsource.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/firstscan/configuringscan.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/firstscan/overview.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/firstscan/runningscan.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/firstscan/viewingresults.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/overview.md create mode 100644 docs/accessanalyzer/1.0/index.md create mode 100644 docs/accessanalyzer/1.0/install/_category_.json create mode 100644 docs/accessanalyzer/1.0/install/dspmctl.md create mode 100644 docs/accessanalyzer/1.0/install/environmentvariables.md create mode 100644 docs/accessanalyzer/1.0/install/network.md create mode 100644 docs/accessanalyzer/1.0/install/overview.md create mode 100644 docs/accessanalyzer/1.0/install/postinstall.md create mode 100644 docs/accessanalyzer/1.0/install/preflight.md create mode 100644 docs/accessanalyzer/1.0/install/quickinstall.md create mode 100644 docs/accessanalyzer/1.0/install/requirements.md create mode 100644 docs/accessanalyzer/1.0/install/security.md create mode 100644 docs/accessanalyzer/1.0/install/ssl.md create mode 100644 docs/accessanalyzer/1.0/install/stepbystep.md create mode 100644 docs/accessanalyzer/1.0/install/uninstall.md create mode 100644 docs/accessanalyzer/1.0/install/upgrade.md create mode 100644 docs/accessanalyzer/1.0/overview/_category_.json create mode 100644 docs/accessanalyzer/1.0/overview/architecture.md create mode 100644 docs/accessanalyzer/1.0/overview/keyconcepts.md create mode 100644 docs/accessanalyzer/1.0/overview/overview.md create mode 100644 docs/accessanalyzer/1.0/requirements/_category_.json create mode 100644 docs/accessanalyzer/1.0/requirements/connectors/_category_.json create mode 100644 docs/accessanalyzer/1.0/requirements/connectors/activedirectory.md create mode 100644 docs/accessanalyzer/1.0/requirements/connectors/cifs.md create mode 100644 docs/accessanalyzer/1.0/requirements/connectors/entraid.md create mode 100644 docs/accessanalyzer/1.0/requirements/connectors/localgroups.md create mode 100644 docs/accessanalyzer/1.0/requirements/connectors/sharepointonline.md create mode 100644 docs/accessanalyzer/1.0/requirements/database/_category_.json create mode 100644 docs/accessanalyzer/1.0/requirements/database/clickhouse.md create mode 100644 docs/accessanalyzer/1.0/requirements/database/postgresql.md create mode 100644 docs/accessanalyzer/1.0/requirements/database/redis.md create mode 100644 docs/accessanalyzer/1.0/requirements/overview.md create mode 100644 docs/accessanalyzer/1.0/requirements/system/_category_.json create mode 100644 docs/accessanalyzer/1.0/requirements/system/hardware.md create mode 100644 docs/accessanalyzer/1.0/requirements/system/kubernetes.md create mode 100644 docs/accessanalyzer/1.0/requirements/system/network.md create mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/_category_.json create mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/overview.md create mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/_category_.json create mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/builtinpatterns.md create mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/custompatterns.md create mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/patterngroups.md create mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/_category_.json create mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/classificationbreakdown.md create mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/matchcounts.md create mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/runningscan.md create mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/_category_.json create mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/autovscustom.md create mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/classificationrules.md create mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/taxonomygroups.md create mode 100644 docs/accessanalyzer/1.0/troubleshooting/_category_.json create mode 100644 docs/accessanalyzer/1.0/troubleshooting/commonissues/_category_.json create mode 100644 docs/accessanalyzer/1.0/troubleshooting/commonissues/connectionfailures.md create mode 100644 docs/accessanalyzer/1.0/troubleshooting/commonissues/databaseconnectivity.md create mode 100644 docs/accessanalyzer/1.0/troubleshooting/commonissues/scanerrors.md create mode 100644 docs/accessanalyzer/1.0/troubleshooting/healthchecks/_category_.json create mode 100644 docs/accessanalyzer/1.0/troubleshooting/healthchecks/endpoints.md create mode 100644 docs/accessanalyzer/1.0/troubleshooting/healthchecks/probes.md create mode 100644 docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/_category_.json create mode 100644 docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/failedjobs.md create mode 100644 docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/queues.md create mode 100644 docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/sidekiq.md create mode 100644 docs/accessanalyzer/1.0/troubleshooting/observability/_category_.json create mode 100644 docs/accessanalyzer/1.0/troubleshooting/observability/opentelemetry.md create mode 100644 docs/accessanalyzer/1.0/troubleshooting/observability/prometheus.md create mode 100644 docs/accessanalyzer/1.0/troubleshooting/overview.md create mode 100644 sidebars/accessanalyzer/1.0.js diff --git a/docs/accessanalyzer/1.0/activitymonitoring/_category_.json b/docs/accessanalyzer/1.0/activitymonitoring/_category_.json new file mode 100644 index 0000000000..0855f40693 --- /dev/null +++ b/docs/accessanalyzer/1.0/activitymonitoring/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Activity Monitoring", + "position": 90, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/activitymonitoring/configuration/_category_.json b/docs/accessanalyzer/1.0/activitymonitoring/configuration/_category_.json new file mode 100644 index 0000000000..4fda61ea66 --- /dev/null +++ b/docs/accessanalyzer/1.0/activitymonitoring/configuration/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Configuration", + "position": 20, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "enablingsyslog" + } +} diff --git a/docs/accessanalyzer/1.0/activitymonitoring/configuration/batchprocessing.md b/docs/accessanalyzer/1.0/activitymonitoring/configuration/batchprocessing.md new file mode 100644 index 0000000000..807ec75106 --- /dev/null +++ b/docs/accessanalyzer/1.0/activitymonitoring/configuration/batchprocessing.md @@ -0,0 +1,8 @@ +--- +title: "Batch Processing Settings" +description: "Configure batch size and processing intervals" +sidebar_position: 30 +draft: true +--- + +# Batch Processing Settings diff --git a/docs/accessanalyzer/1.0/activitymonitoring/configuration/connectingnam.md b/docs/accessanalyzer/1.0/activitymonitoring/configuration/connectingnam.md new file mode 100644 index 0000000000..3f9bdba5f0 --- /dev/null +++ b/docs/accessanalyzer/1.0/activitymonitoring/configuration/connectingnam.md @@ -0,0 +1,8 @@ +--- +title: "Connecting Netwrix Activity Monitor" +description: "Configure NAM to send events to Access Analyzer" +sidebar_position: 20 +draft: true +--- + +# Connecting Netwrix Activity Monitor diff --git a/docs/accessanalyzer/1.0/activitymonitoring/configuration/enablingsyslog.md b/docs/accessanalyzer/1.0/activitymonitoring/configuration/enablingsyslog.md new file mode 100644 index 0000000000..ed154c8585 --- /dev/null +++ b/docs/accessanalyzer/1.0/activitymonitoring/configuration/enablingsyslog.md @@ -0,0 +1,8 @@ +--- +title: "Enabling Syslog Ingestion" +description: "Enable the syslog listener for activity data" +sidebar_position: 10 +draft: true +--- + +# Enabling Syslog Ingestion diff --git a/docs/accessanalyzer/1.0/activitymonitoring/overview.md b/docs/accessanalyzer/1.0/activitymonitoring/overview.md new file mode 100644 index 0000000000..1db4669826 --- /dev/null +++ b/docs/accessanalyzer/1.0/activitymonitoring/overview.md @@ -0,0 +1,8 @@ +--- +title: "Activity Monitoring" +description: "Monitor file access and user activity via Netwrix Activity Monitor" +sidebar_position: 1 +draft: true +--- + +# Activity Monitoring diff --git a/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/_category_.json b/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/_category_.json new file mode 100644 index 0000000000..0f66039da8 --- /dev/null +++ b/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Viewing Activity Data", + "position": 30, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "fileaccessevents" + } +} diff --git a/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/fileaccessevents.md b/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/fileaccessevents.md new file mode 100644 index 0000000000..e914857e32 --- /dev/null +++ b/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/fileaccessevents.md @@ -0,0 +1,8 @@ +--- +title: "File Access Events" +description: "Viewing file access event data" +sidebar_position: 10 +draft: true +--- + +# File Access Events diff --git a/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/useractivitypatterns.md b/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/useractivitypatterns.md new file mode 100644 index 0000000000..b22d570ef1 --- /dev/null +++ b/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/useractivitypatterns.md @@ -0,0 +1,8 @@ +--- +title: "User Activity Patterns" +description: "Analyzing user activity trends and patterns" +sidebar_position: 20 +draft: true +--- + +# User Activity Patterns diff --git a/docs/accessanalyzer/1.0/admin/_category_.json b/docs/accessanalyzer/1.0/admin/_category_.json new file mode 100644 index 0000000000..8ba9f88730 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Administration", + "position": 50, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/admin/auditlogs/_category_.json b/docs/accessanalyzer/1.0/admin/auditlogs/_category_.json new file mode 100644 index 0000000000..08737ee73a --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/auditlogs/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Audit Logs", + "position": 100, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/admin/auditlogs/export.md b/docs/accessanalyzer/1.0/admin/auditlogs/export.md new file mode 100644 index 0000000000..5f46de33f4 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/auditlogs/export.md @@ -0,0 +1,43 @@ +--- +title: "Log Export" +description: "Exporting audit log data" +sidebar_position: 20 +--- + +# Log Export + +Administrators can export audit log data for external analysis, compliance reporting, or long-term archival. The export feature generates a downloadable file containing the filtered audit log entries. + +## Exporting Logs + +To export audit logs: + +1. Navigate to **Audit Logs** in the sidebar. +2. Apply any desired filters (date range, user, action type, resource type) to narrow the export scope. +3. Click **Export**. +4. Select the export format: + +| Format | Description | +|---|---| +| **CSV** | Comma-separated values, compatible with spreadsheet applications and data analysis tools | +| **JSON** | Structured JSON format, suitable for programmatic processing and SIEM ingestion | + +5. Click **Download** to save the file. + +## Export Scope + +The export includes all audit log entries matching the current filter criteria. If no filters are applied, the export contains all available audit log records. + +:::note +Large exports may take several minutes to generate. The download begins automatically when the file is ready. +::: + +## Use Cases + +- **Compliance Audits** -- Provide auditors with a complete trail of administrative actions over a specified period. +- **SIEM Integration** -- Export logs in JSON format for ingestion into security information and event management platforms. +- **Archival** -- Periodically export and archive audit logs to external storage for long-term retention. + +:::warning +Exported audit log files may contain sensitive information about users and system configuration. Handle exported files in accordance with your organization's data handling policies. +::: diff --git a/docs/accessanalyzer/1.0/admin/auditlogs/overview.md b/docs/accessanalyzer/1.0/admin/auditlogs/overview.md new file mode 100644 index 0000000000..fa30bc76ae --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/auditlogs/overview.md @@ -0,0 +1,39 @@ +--- +title: "Audit Logs" +description: "Viewing system activity and audit trail" +sidebar_position: 10 +--- + +# Audit Logs + +Access Analyzer maintains a comprehensive audit trail of all user actions. Audit logs capture who performed an action, what was changed, and when the event occurred. This data supports security reviews, compliance audits, and incident investigations. + +## Viewing Audit Logs + +Navigate to **Audit Logs** in the sidebar to access the log viewer. The audit log table displays: + +| Column | Description | +|---|---| +| **Timestamp** | Date and time of the action | +| **User** | The user who performed the action | +| **Action** | The type of operation (e.g., Create, Update, Delete, Login, Logout) | +| **Resource** | The affected resource type and identifier | +| **Details** | Additional context about the change, including before and after values where applicable | +| **IP Address** | The client IP from which the action was performed | + +## Filtering and Searching + +Use the table controls to filter audit logs by: + +- **Date range** -- Specify start and end dates. +- **User** -- Filter by a specific user. +- **Action type** -- Show only specific action types. +- **Resource type** -- Filter by resource category (e.g., Source, Scan, User). + +## Log Retention + +Audit logs are retained for the duration configured in application settings. By default, logs are retained indefinitely. + +## Related Topics + +- [Log Export](/docs/accessanalyzer/1_0/admin/auditlogs/export) diff --git a/docs/accessanalyzer/1.0/admin/authentication/_category_.json b/docs/accessanalyzer/1.0/admin/authentication/_category_.json new file mode 100644 index 0000000000..b4206ec509 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/authentication/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Authentication", + "position": 30, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/admin/authentication/overview.md b/docs/accessanalyzer/1.0/admin/authentication/overview.md new file mode 100644 index 0000000000..cea13a2a43 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/authentication/overview.md @@ -0,0 +1,34 @@ +--- +title: "Authentication" +description: "Login workflow and session lifecycle" +sidebar_position: 10 +--- + +# Authentication + +Access Analyzer uses session-based authentication backed by Redis for secure, server-side session storage. All API endpoints under `/api/v1/` require a valid session, except for the login endpoint. + +## Login Workflow + +1. The user submits their **username** and **password** via the login form. +2. The server validates the credentials against the stored Argon2id password hash. +3. On success, a new session is created in Redis and a session cookie is returned to the client. +4. The client includes the session cookie with all subsequent API requests. + +## Session Lifecycle + +Each session progresses through the following states: + +- **Active** -- The session is valid and the user is authenticated. +- **Refreshed** -- The session token has been refreshed before expiration. See [Token Refresh and Expiration](/docs/accessanalyzer/1_0/admin/authentication/tokenrefresh). +- **Expired** -- The session TTL has elapsed and the user must re-authenticate. +- **Revoked** -- An administrator has manually terminated the session. + +## IP Validation + +Access Analyzer validates the client IP address on each request. If a request originates from an IP that does not match the session's originating IP, the session is invalidated and the user must log in again. + +## Related Topics + +- [Token Refresh and Expiration](/docs/accessanalyzer/1_0/admin/authentication/tokenrefresh) +- [Session Monitoring and Revocation](/docs/accessanalyzer/1_0/admin/authentication/sessionmonitoring) diff --git a/docs/accessanalyzer/1.0/admin/authentication/sessionmonitoring.md b/docs/accessanalyzer/1.0/admin/authentication/sessionmonitoring.md new file mode 100644 index 0000000000..15ad434a40 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/authentication/sessionmonitoring.md @@ -0,0 +1,38 @@ +--- +title: "Session Monitoring and Revocation" +description: "Monitoring active sessions and revoking access" +sidebar_position: 30 +--- + +# Session Monitoring and Revocation + +Administrators can monitor all active sessions across the application and revoke access when needed. This is useful for responding to security incidents or enforcing access policies. + +## Monitoring Active Sessions + +The session monitoring view is accessible from **Users** > **Sessions**. It provides a real-time view of all authenticated sessions, including: + +- **Username** and assigned role +- **Client IP address** and geographic context +- **Session start time** and **last activity** timestamp +- **Remaining TTL** before automatic expiration + +Use the table's filter and sort controls to locate specific sessions by user, IP address, or activity time. + +## Revoking Sessions + +To revoke one or more sessions: + +1. Select the target sessions using the row checkboxes. +2. Click **Revoke Selected**. +3. Confirm the action in the dialog. + +Revocation is immediate. The affected sessions are removed from Redis and all subsequent requests using those session tokens return `401 Unauthorized`. + +## Bulk Revocation + +To revoke all sessions for a specific user, navigate to the user's detail page and click **Revoke All Sessions**. This is recommended when a user account may be compromised. + +:::warning +Session revocation cannot be undone. Affected users must log in again to regain access. +::: diff --git a/docs/accessanalyzer/1.0/admin/authentication/tokenrefresh.md b/docs/accessanalyzer/1.0/admin/authentication/tokenrefresh.md new file mode 100644 index 0000000000..ee1dbd8250 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/authentication/tokenrefresh.md @@ -0,0 +1,34 @@ +--- +title: "Token Refresh and Expiration" +description: "How access tokens are refreshed and session expiration" +sidebar_position: 20 +--- + +# Token Refresh and Expiration + +Access Analyzer sessions have a configurable time-to-live (TTL). To prevent unnecessary re-authentication, sessions are automatically refreshed during active use. + +## How Token Refresh Works + +When a user makes an API request and the session is past the halfway point of its TTL, the server automatically issues a new session token. This process is transparent to the user: + +1. The client sends a request with the current session cookie. +2. The server detects that the session has passed 50% of its TTL. +3. A new session token is generated and the old token is invalidated. +4. The response includes the updated session cookie. + +## Session Expiration + +Sessions expire when the full TTL elapses without any qualifying refresh. When a session expires: + +- All subsequent API requests return a `401 Unauthorized` response. +- The user is redirected to the login page. +- The expired session record is automatically purged from Redis. + +## Configuration + +Session TTL and refresh behavior are configured in the application settings. See [Session and Token TTL](/docs/accessanalyzer/1_0/admin/settings/sessionttl) for configuration details. + +:::note +Token refresh only occurs during active requests. Background tabs or idle browser windows do not trigger a refresh. +::: diff --git a/docs/accessanalyzer/1.0/admin/iam/_category_.json b/docs/accessanalyzer/1.0/admin/iam/_category_.json new file mode 100644 index 0000000000..762c39d494 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/iam/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "IAM Services", + "position": 80, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/admin/iam/identitiesentitlements.md b/docs/accessanalyzer/1.0/admin/iam/identitiesentitlements.md new file mode 100644 index 0000000000..d0fedf9ee1 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/iam/identitiesentitlements.md @@ -0,0 +1,36 @@ +--- +title: "Viewing Identities and Entitlements" +description: "Browsing synced users and their permissions" +sidebar_position: 30 +--- + +# Viewing Identities and Entitlements + +After identity synchronization completes, administrators and viewers can browse the unified identity directory and review entitlements across all scanned sources. + +## Identity List + +Navigate to **IAM** > **Identities** to view all synced identities. The table displays: + +| Column | Description | +|---|---| +| **Display Name** | The user or group name | +| **Type** | User or Group | +| **Provider** | Source directory (Active Directory, Entra ID, Local Groups) | +| **Email** | Associated email address, if available | +| **Group Count** | Number of groups the identity belongs to | +| **Last Synced** | Timestamp of the most recent sync | + +Use the filter controls to narrow results by provider, type, or keyword search. + +## Entitlement Details + +Click an identity to open the detail view, which includes: + +- **Group Memberships** -- All groups the identity belongs to, including nested group membership. +- **Resource Access** -- A list of sources and resources the identity can access, with the effective permission level. +- **Permission Paths** -- Links to the [Permission Path Analysis](/docs/accessanalyzer/1_0/admin/iam/permissionpaths) for each access entry, showing how the permission was granted. + +## Cross-Provider Correlation + +When the same user exists in multiple directories, Access Analyzer correlates these identities and displays a unified view. Correlated accounts are indicated with a badge showing the linked providers. diff --git a/docs/accessanalyzer/1.0/admin/iam/identitysync.md b/docs/accessanalyzer/1.0/admin/iam/identitysync.md new file mode 100644 index 0000000000..784bd209da --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/iam/identitysync.md @@ -0,0 +1,43 @@ +--- +title: "Identity Sync Process" +description: "How identities are synchronized from IAM providers" +sidebar_position: 20 +--- + +# Identity Sync Process + +Identity synchronization imports user and group data from configured IAM providers into Access Analyzer. This data forms the foundation for entitlement analysis and permission path reporting. + +## How Sync Works + +The identity sync process performs the following steps: + +1. Connects to each configured IAM source (Active Directory, Entra ID, or Local Groups) using the associated service account credentials. +2. Retrieves user accounts, groups, and membership relationships. +3. Normalizes identity data into a unified format across providers. +4. Stores the synchronized identities in the Access Analyzer database. +5. Correlates identities across multiple providers when the same user appears in more than one directory. + +## Triggering a Sync + +Identity sync occurs automatically during access scan execution. It can also be triggered manually: + +1. Navigate to **IAM** in the sidebar. +2. Click **Sync Now**. +3. Monitor the sync progress in the status indicator. + +## Sync Frequency + +Each access scan triggers a fresh identity sync for its target sources. For environments that change frequently, schedule access scans at regular intervals to keep identity data current. + +## Sync Status + +| Status | Description | +|---|---| +| **In Progress** | Sync is actively importing identity data | +| **Completed** | Sync finished successfully with a timestamp | +| **Failed** | Sync encountered an error; check system logs for details | + +:::note +Identity sync only imports identity metadata (usernames, group names, memberships). It does not import passwords or other credential data. +::: diff --git a/docs/accessanalyzer/1.0/admin/iam/overview.md b/docs/accessanalyzer/1.0/admin/iam/overview.md new file mode 100644 index 0000000000..60b42bffc2 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/iam/overview.md @@ -0,0 +1,32 @@ +--- +title: "IAM Services" +description: "Configuring identity and access management integrations" +sidebar_position: 10 +--- + +# IAM Services + +The IAM section provides tools for synchronizing identities from external directories and analyzing access entitlements across your environment. This enables centralized visibility into who has access to what resources and how that access was granted. + +## Supported IAM Providers + +Access Analyzer synchronizes identity data from the following sources: + +| Provider | Identity Data | +|---|---| +| **Active Directory** | Users, groups, group memberships, organizational units | +| **Entra ID** | Users, groups, application role assignments | +| **Local Groups** | Local users and group memberships on Windows servers | + +## Key Capabilities + +- **Identity Synchronization** -- Import users and groups from configured IAM providers. See [Identity Sync Process](/docs/accessanalyzer/1_0/admin/iam/identitysync). +- **Identities and Entitlements** -- Browse synced identities and view their effective permissions across sources. See [Viewing Identities and Entitlements](/docs/accessanalyzer/1_0/admin/iam/identitiesentitlements). +- **Permission Path Analysis** -- Trace the path from a user to a resource to understand how access was granted. See [Permission Path Analysis](/docs/accessanalyzer/1_0/admin/iam/permissionpaths). + +## Prerequisites + +Before using IAM features, ensure that: + +- At least one Active Directory, Entra ID, or Local Groups source is configured with valid credentials. +- An access scan has been completed for the target sources. diff --git a/docs/accessanalyzer/1.0/admin/iam/permissionpaths.md b/docs/accessanalyzer/1.0/admin/iam/permissionpaths.md new file mode 100644 index 0000000000..c119a02184 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/iam/permissionpaths.md @@ -0,0 +1,39 @@ +--- +title: "Permission Path Analysis" +description: "Analyzing permission paths and access relationships" +sidebar_position: 40 +--- + +# Permission Path Analysis + +Permission path analysis traces the chain of access from an identity to a resource, showing every group membership, permission assignment, and inheritance step that grants access. This is essential for understanding why a user has access to a particular resource. + +## Viewing Permission Paths + +To view permission paths for a specific identity: + +1. Navigate to **IAM** > **Identities** and select the target identity. +2. In the **Resource Access** section, click the **View Path** link next to any resource entry. + +The permission path visualization displays the chain as a directional graph: + +**User** > **Group** > **Nested Group** > **Permission Assignment** > **Resource** + +## Path Components + +| Component | Description | +|---|---| +| **Identity** | The starting user or group | +| **Group Membership** | Direct or nested group that the identity belongs to | +| **Permission Entry** | The specific ACL or role assignment that grants access | +| **Resource** | The target file share, site, directory object, or folder | + +## Use Cases + +- **Access Reviews** -- Determine whether a user's access is appropriate and through which path it was granted. +- **Least Privilege Analysis** -- Identify overly broad group memberships that grant unintended access. +- **Incident Response** -- Trace access paths for a compromised account to assess the scope of exposure. + +:::note +Permission paths are computed from the most recent access scan results. Run a new scan to capture changes in group memberships or permission assignments. +::: diff --git a/docs/accessanalyzer/1.0/admin/navigate/_category_.json b/docs/accessanalyzer/1.0/admin/navigate/_category_.json new file mode 100644 index 0000000000..b9960d7f84 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/navigate/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Navigating the Web Interface", + "position": 10, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/admin/navigate/datatables.md b/docs/accessanalyzer/1.0/admin/navigate/datatables.md new file mode 100644 index 0000000000..4c976fa57d --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/navigate/datatables.md @@ -0,0 +1,35 @@ +--- +title: "Data Tables" +description: "Sorting, filtering, and pagination in data tables" +sidebar_position: 30 +--- + +# Data Tables + +Data tables are used throughout the Access Analyzer interface to display collections of records such as sources, scans, users, and audit log entries. Each table supports sorting, filtering, and pagination. + +## Sorting + +Click a column header to sort the table by that column. Click the same header again to toggle between ascending and descending order. A directional arrow icon indicates the current sort direction. + +## Filtering + +Use the filter controls above the table to narrow results: + +- **Text search** -- Enter a keyword to filter rows that match across visible columns. +- **Column filters** -- Some tables provide dropdown filters for specific columns such as status, type, or date range. + +## Pagination + +Tables with large datasets are paginated. Use the controls at the bottom of the table to: + +- Navigate between pages using **Previous** and **Next** buttons. +- Select the number of rows displayed per page (e.g., 10, 25, 50, 100). + +## Bulk Actions + +On supported tables, select one or more rows using the checkbox column to enable bulk actions. Available bulk actions vary by context and may include **Delete**, **Run Scan**, or **Export**. + +:::note +Table state (sort order, active filters, current page) resets when you navigate away from the page. +::: diff --git a/docs/accessanalyzer/1.0/admin/navigate/overview.md b/docs/accessanalyzer/1.0/admin/navigate/overview.md new file mode 100644 index 0000000000..9662e7ffe0 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/navigate/overview.md @@ -0,0 +1,27 @@ +--- +title: "Navigating the Web Interface" +description: "Overview of the Access Analyzer web interface" +sidebar_position: 10 +--- + +# Navigating the Web Interface + +Netwrix Access Analyzer provides a web-based interface for managing all configuration and reporting tasks. The interface is organized into a persistent sidebar for primary navigation and a main content area that displays contextual data tables, forms, and dashboards. + +## Interface Layout + +The web interface consists of the following regions: + +- **Sidebar** -- The left-hand navigation panel provides access to all major sections including Sources, Scans, IAM, Sensitive Data, Settings, and Audit Logs. See [Sidebar Navigation](/docs/accessanalyzer/1_0/admin/navigate/sidebar) for details. +- **Header bar** -- Displays the current user, session status, and a logout control. +- **Main content area** -- Renders the active page content including data tables, detail views, and configuration forms. + +## Key Concepts + +- Most list views use paginated [Data Tables](/docs/accessanalyzer/1_0/admin/navigate/datatables) with sorting, filtering, and search capabilities. +- Breadcrumbs at the top of the content area indicate your current location in the navigation hierarchy. +- Action buttons such as **Create**, **Edit**, and **Delete** appear contextually based on the active page and your user role. + +:::note +The interface requires a modern web browser with JavaScript enabled. Supported browsers include the latest versions of Chrome, Edge, and Firefox. +::: diff --git a/docs/accessanalyzer/1.0/admin/navigate/sidebar.md b/docs/accessanalyzer/1.0/admin/navigate/sidebar.md new file mode 100644 index 0000000000..db30881ccf --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/navigate/sidebar.md @@ -0,0 +1,34 @@ +--- +title: "Sidebar Navigation" +description: "Using the sidebar to navigate between sections" +sidebar_position: 20 +--- + +# Sidebar Navigation + +The sidebar is the primary navigation element in the Access Analyzer web interface. It remains visible on every page and provides direct access to all major administration sections. + +## Sidebar Sections + +The sidebar contains the following top-level entries: + +| Section | Purpose | +|---|---| +| **Dashboard** | Application overview and summary metrics | +| **Sources** | Manage data sources and source groups | +| **Scans** | Create, schedule, and monitor scans | +| **IAM** | View synced identities, entitlements, and permission paths | +| **Sensitive Data** | Configure classification patterns and taxonomy rules | +| **Service Accounts** | Manage credentials for source connections | +| **Settings** | Application-wide configuration | +| **Audit Logs** | Review user action history | +| **System Logs** | View application and job processing logs | +| **Users** | Manage user accounts and sessions | + +## Collapsible Groups + +Some sidebar entries expand to reveal sub-items. Click a section label to toggle its children. The currently active page is highlighted with a visual indicator. + +## Role-Based Visibility + +Users with the **Viewer** role see a reduced sidebar. Administrative sections such as **Settings** and **Users** are hidden for non-administrator accounts. diff --git a/docs/accessanalyzer/1.0/admin/overview.md b/docs/accessanalyzer/1.0/admin/overview.md new file mode 100644 index 0000000000..0b759ccd84 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/overview.md @@ -0,0 +1,29 @@ +--- +title: "Administration" +description: "Manage users, sources, scans, and system settings" +sidebar_position: 1 +--- + +# Administration + +The Administration section provides tools for configuring and managing all aspects of Netwrix Access Analyzer. From here, administrators can control user access, define data sources, configure scans, and maintain system settings. + +## Admin Sections + +| Section | Description | +|---|---| +| [Navigation](/docs/accessanalyzer/1_0/admin/navigate/overview) | Learn how to navigate the web interface, use the sidebar, and interact with data tables | +| [Users](/docs/accessanalyzer/1_0/admin/users/overview) | Create and manage user accounts, assign roles, and monitor sessions | +| [Authentication](/docs/accessanalyzer/1_0/admin/authentication/overview) | Configure login workflows, session lifecycle, and token management | +| [Sources](/docs/accessanalyzer/1_0/admin/sources/overview) | Add and manage data sources for scanning | +| [Service Accounts](/docs/accessanalyzer/1_0/admin/serviceaccounts/overview) | Manage credentials used to connect to data sources | +| [Scans](/docs/accessanalyzer/1_0/admin/scans/overview) | Create, schedule, and monitor access and sensitive data scans | +| [Sensitive Data](/docs/accessanalyzer/1_0/admin/sensitivedata/overview) | Configure classification patterns, taxonomy groups, and compliance mappings | +| [IAM](/docs/accessanalyzer/1_0/admin/iam/overview) | Synchronize identities and analyze entitlements and permission paths | +| [Settings](/docs/accessanalyzer/1_0/admin/settings/overview) | Configure application-wide settings, scan limits, and feature flags | +| [Audit Logs](/docs/accessanalyzer/1_0/admin/auditlogs/overview) | Review and export the full user action audit trail | +| [System Logs](/docs/accessanalyzer/1_0/admin/systemlogs) | View application-level system logs and Sidekiq job monitoring | + +:::note +Only users with the **Administrator** role have full access to all administration functions. Users with the **Viewer** role have read-only access. +::: diff --git a/docs/accessanalyzer/1.0/admin/scans/_category_.json b/docs/accessanalyzer/1.0/admin/scans/_category_.json new file mode 100644 index 0000000000..27b262b756 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/scans/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Scan Management", + "position": 60, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/admin/scans/executionhistory.md b/docs/accessanalyzer/1.0/admin/scans/executionhistory.md new file mode 100644 index 0000000000..4afaf84df1 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/scans/executionhistory.md @@ -0,0 +1,44 @@ +--- +title: "Scan Execution History" +description: "Viewing scan status and execution history" +sidebar_position: 50 +--- + +# Scan Execution History + +Every scan execution is recorded with detailed status information, timing, and result summaries. The execution history provides a complete audit trail of all scan activity. + +## Viewing Execution History + +To view a scan's history: + +1. Navigate to **Scans** and click the target scan. +2. Select the **History** tab in the detail view. + +The history table displays each execution with the following columns: + +| Column | Description | +|---|---| +| **Run ID** | Unique identifier for the execution | +| **Status** | Final status (Completed, Failed, Stopped) | +| **Started At** | Timestamp when the execution began | +| **Completed At** | Timestamp when the execution ended | +| **Duration** | Total elapsed time | +| **Items Processed** | Number of resources scanned | +| **Findings** | Count of access entries or sensitive data matches found | + +## Execution Details + +Click a specific execution row to view detailed results including: + +- Per-source breakdown of items scanned and findings +- Error messages for failed executions +- Resource utilization metrics + +## Retention + +Execution history records are retained indefinitely. To manage storage, administrators can export and archive older records through the [Audit Logs](/docs/accessanalyzer/1_0/admin/auditlogs/overview) export feature. + +:::note +Execution history for deleted scans is also removed. Export any needed data before deleting a scan. +::: diff --git a/docs/accessanalyzer/1.0/admin/scans/overview.md b/docs/accessanalyzer/1.0/admin/scans/overview.md new file mode 100644 index 0000000000..fb917e14a4 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/scans/overview.md @@ -0,0 +1,31 @@ +--- +title: "Scan Management" +description: "Creating and managing scans" +sidebar_position: 10 +--- + +# Scan Management + +Scans are the core operational unit in Access Analyzer. A scan defines what sources to analyze, what type of analysis to perform, and when to execute. Administrators create and manage scans from the **Scans** section. + +## Creating Scans + +Scans are typically created as part of the **Connect Source** wizard (Step 3), where you configure scan types, options, and scheduling alongside the source group. The wizard creates all scans atomically with the source group and sources. + +Scans can also be managed independently after creation: + +1. Navigate to **Scans** in the sidebar. +2. Select a scan to view or edit its configuration. +3. Modify the schedule, scan options, or other settings. +4. Click **Save**. + +## Scan List + +The scan list displays all configured scans with their name, type, target sources, schedule, last execution status, and next scheduled run time. Use the data table controls to filter and sort. + +## Related Topics + +- [Scan Types](/docs/accessanalyzer/1_0/admin/scans/scantypes) +- [Scheduling Scans](/docs/accessanalyzer/1_0/admin/scans/scheduling) +- [Running and Stopping Scans](/docs/accessanalyzer/1_0/admin/scans/runningstop) +- [Scan Execution History](/docs/accessanalyzer/1_0/admin/scans/executionhistory) diff --git a/docs/accessanalyzer/1.0/admin/scans/runningstop.md b/docs/accessanalyzer/1.0/admin/scans/runningstop.md new file mode 100644 index 0000000000..3df1773d7f --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/scans/runningstop.md @@ -0,0 +1,42 @@ +--- +title: "Running and Stopping Scans" +description: "Executing scans and graceful stop" +sidebar_position: 40 +--- + +# Running and Stopping Scans + +Administrators can manually trigger scan execution and control running scans through the web interface. These controls are available from the scan detail view and the scan list. + +## Running a Scan Manually + +To start a scan immediately: + +1. Navigate to **Scans** in the sidebar. +2. Locate the scan and click **Run** (or open the detail view and click **Run Now**). +3. The scan status changes to **Running** and progress is displayed in real time. + +## Scan Controls + +While a scan is running, the following controls are available: + +| Action | Description | +|---|---| +| **Pause** | Temporarily suspends scan execution. The scan can be resumed from where it stopped. | +| **Resume** | Continues a paused scan from its last checkpoint. | +| **Stop** | Initiates a graceful stop. The scan finishes processing the current item and then terminates. | + +## Scan Status Values + +| Status | Meaning | +|---|---| +| **Pending** | The scan is queued and waiting to start | +| **Running** | The scan is actively processing | +| **Paused** | The scan is suspended and can be resumed | +| **Completing** | The scan is finishing its current work unit after a stop request | +| **Completed** | The scan finished successfully | +| **Failed** | The scan terminated due to an error | + +:::warning +Stopping a scan does not roll back any data already collected. Partial results are retained and visible in the scan history. +::: diff --git a/docs/accessanalyzer/1.0/admin/scans/scantypes.md b/docs/accessanalyzer/1.0/admin/scans/scantypes.md new file mode 100644 index 0000000000..39ba1911a2 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/scans/scantypes.md @@ -0,0 +1,64 @@ +--- +title: "Scan Types" +description: "Access, sensitive data, identity sync, and local users scan types" +sidebar_position: 20 +--- + +# Scan Types + +Access Analyzer supports several scan types, each designed to analyze different aspects of your data environment. Scan types are selected during the Connect Source wizard (Step 3) and determine what data is collected and reported. + +## Access Scans + +Access scans analyze permissions and access controls on the target sources. They collect: + +- User and group permission assignments +- Effective access rights +- Permission inheritance paths +- Share and folder-level access control lists + +Access scans are available for **CIFS** (File Server), **SharePoint**, **Active Directory**, and **Local Groups** source types. + +For File Server sources, access scans support additional configuration options including share filtering, scan depth, file-level permissions, hidden share enumeration, and worker threads. See [CIFS Connector](/docs/accessanalyzer/1_0/connectors/source/cifs/connectionconfig) for details. + +## Sensitive Data Scans + +Sensitive data scans inspect file content to identify data matching configured classification patterns. They detect: + +- Personally identifiable information (PII) +- Financial data (credit card numbers, bank account numbers) +- Protected health information (PHI) +- Credentials and secrets +- Custom patterns defined in [Sensitive Data Configuration](/docs/accessanalyzer/1_0/admin/sensitivedata/overview) + +Sensitive data scans are available for **CIFS** and **SharePoint** source types only. + +## Identity Sync Scans + +Identity sync scans retrieve users, groups, and permissions from identity providers: + +| Scan | Source Type | Description | +| --- | --- | --- | +| **Active Directory Inventory** | Active Directory | Synchronizes users, groups, OUs, and domain permissions | +| **Users, Groups and Roles** | Entra ID | Synchronizes Azure AD users, groups, directory roles, and optionally sensitivity labels | + +For Entra ID, the identity sync scan is always enabled and cannot be disabled. + +## Local Users and Groups Scans + +When an **Access** scan is enabled for a File Server source, a **Local Users and Groups** scan is automatically created alongside it. This scan collects local user and group account data from each file server, which is used to resolve local account references found in NTFS ACLs. + +This scan type does not require separate configuration — it inherits the same schedule as the access scan. + +## Comparison + +| Feature | Access Scan | Sensitive Data Scan | Identity Sync | Local Users and Groups | +|---|---|---|---|---| +| Analyzes permissions | Yes | No | No | No | +| Inspects file content | No | Yes | No | No | +| Syncs identities | No | No | Yes | Yes | +| Supported sources | CIFS, SharePoint, AD, Local Groups | CIFS, SharePoint | AD, Entra ID | CIFS (auto-created) | + +:::note +A single source can have multiple scan types configured independently, each with its own schedule. +::: diff --git a/docs/accessanalyzer/1.0/admin/scans/scheduling.md b/docs/accessanalyzer/1.0/admin/scans/scheduling.md new file mode 100644 index 0000000000..f1088e482d --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/scans/scheduling.md @@ -0,0 +1,50 @@ +--- +title: "Scheduling Scans" +description: "Configuring cron-based scan schedules" +sidebar_position: 30 +--- + +# Scheduling Scans + +Scans can be configured to run automatically on a recurring schedule using cron expressions. Scheduled scans are processed by the Sidekiq background job system. + +## Setting a Schedule + +To schedule a scan: + +1. Navigate to **Scans** and open the scan detail view. +2. Click **Edit**. +3. In the **Schedule** section, enable **Scheduled Execution**. +4. Enter a cron expression or use the visual schedule builder to define the frequency. +5. Click **Save**. + +## Cron Expression Format + +Schedules use standard five-field cron syntax: + +``` +* * * * * +| | | | | +| | | | +-- Day of week (0-6, Sunday=0) +| | | +---- Month (1-12) +| | +------ Day of month (1-31) +| +-------- Hour (0-23) ++---------- Minute (0-59) +``` + +**Examples:** + +| Expression | Description | +|---|---| +| `0 2 * * *` | Daily at 2:00 AM | +| `0 0 * * 0` | Weekly on Sunday at midnight | +| `0 6 1 * *` | Monthly on the 1st at 6:00 AM | +| `0 */4 * * *` | Every 4 hours | + +## Disabling a Schedule + +To stop a scan from running automatically, edit the scan and disable **Scheduled Execution**. The scan configuration is preserved and can be re-enabled later or run manually. + +:::note +All schedule times are interpreted in the server's configured timezone. +::: diff --git a/docs/accessanalyzer/1.0/admin/sensitivedata/_category_.json b/docs/accessanalyzer/1.0/admin/sensitivedata/_category_.json new file mode 100644 index 0000000000..6b56ea467a --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/sensitivedata/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Sensitive Data Configuration", + "position": 70, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/admin/sensitivedata/customclassification.md b/docs/accessanalyzer/1.0/admin/sensitivedata/customclassification.md new file mode 100644 index 0000000000..732fcd762f --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/sensitivedata/customclassification.md @@ -0,0 +1,44 @@ +--- +title: "Custom Classification" +description: "Creating custom classification rules" +sidebar_position: 40 +--- + +# Custom Classification + +In addition to built-in patterns, administrators can create custom classification rules to detect organization-specific sensitive data types. Custom rules use regular expressions and integrate with the existing pattern and taxonomy group framework. + +## Creating a Custom Pattern + +To create a custom pattern: + +1. Navigate to **Sensitive Data** > **Pattern Groups**. +2. Select an existing group or click **Create Group** to define a new pattern group. +3. Click **Add Pattern**. +4. Complete the following fields: + +| Field | Description | +|---|---| +| **Name** | A descriptive label (e.g., "Internal Employee ID") | +| **Regex** | The regular expression to match against file content | +| **Confidence** | Expected accuracy level: **High**, **Medium**, or **Low** | +| **Description** | Optional notes about what the pattern detects | + +5. Click **Save**. + +## Creating a Custom Pattern Group + +Custom pattern groups organize related custom patterns under a shared label. To create a group: + +1. Click **Create Group** from the Pattern Groups page. +2. Enter a **Name** and optional **Description**. +3. Add one or more patterns to the group. +4. Click **Save**. + +## Mapping Custom Patterns to Taxonomy Groups + +To include custom patterns in compliance reporting, associate the custom pattern group with one or more taxonomy groups. Edit the taxonomy group and add the custom pattern group to its list of associated patterns. + +:::warning +Test custom regex patterns thoroughly before enabling them in production scans. Overly broad patterns can generate excessive false positives and impact scan performance. +::: diff --git a/docs/accessanalyzer/1.0/admin/sensitivedata/overview.md b/docs/accessanalyzer/1.0/admin/sensitivedata/overview.md new file mode 100644 index 0000000000..ba8d0bb074 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/sensitivedata/overview.md @@ -0,0 +1,34 @@ +--- +title: "Sensitive Data Configuration" +description: "Configuring patterns and classification rules" +sidebar_position: 10 +--- + +# Sensitive Data Configuration + +The Sensitive Data section allows administrators to configure how Access Analyzer identifies and classifies sensitive information during scans. Classification is driven by regex-based patterns organized into pattern groups and taxonomy groups. + +## How Classification Works + +During a sensitive data scan, Access Analyzer inspects file content against all enabled patterns. When a match is found, the file is tagged with the corresponding classification labels and compliance framework mappings. + +## Configuration Components + +| Component | Description | +|---|---| +| [Pattern Groups](/docs/accessanalyzer/1_0/admin/sensitivedata/patterngroups) | Collections of regex patterns that define what constitutes sensitive data (e.g., PII, Credentials) | +| [Taxonomy Groups](/docs/accessanalyzer/1_0/admin/sensitivedata/taxonomygroups) | Compliance-oriented groupings that map patterns to regulatory frameworks (e.g., GDPR, HIPAA) | +| [Custom Classification](/docs/accessanalyzer/1_0/admin/sensitivedata/customclassification) | User-defined patterns and rules for organization-specific data types | + +## Built-in Categories + +Access Analyzer ships with built-in patterns for common sensitive data categories: + +- **PII** -- Social Security numbers, email addresses, phone numbers, names +- **Credentials** -- API keys, passwords, connection strings, tokens +- **PHI** -- Medical record numbers, diagnosis codes, patient identifiers +- **Financial** -- Credit card numbers, bank account numbers, routing numbers + +:::note +Built-in patterns cannot be deleted but can be disabled if they are not relevant to your environment. +::: diff --git a/docs/accessanalyzer/1.0/admin/sensitivedata/patterngroups.md b/docs/accessanalyzer/1.0/admin/sensitivedata/patterngroups.md new file mode 100644 index 0000000000..2179380a16 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/sensitivedata/patterngroups.md @@ -0,0 +1,43 @@ +--- +title: "Patterns and Pattern Groups" +description: "Managing regex patterns and pattern groups" +sidebar_position: 20 +--- + +# Patterns and Pattern Groups + +Patterns are regular expressions that Access Analyzer uses to identify sensitive data within file content. Patterns are organized into groups for easier management and selective enablement. + +## Pattern Groups + +A pattern group is a named collection of related patterns. Built-in groups include: + +| Group | Examples | +|---|---| +| **PII** | Social Security numbers, driver's license numbers, passport numbers | +| **Credentials** | API keys, passwords in config files, SSH private keys | +| **PHI** | Medical record numbers, health plan IDs, diagnosis codes | +| **Financial** | Credit card numbers (Visa, MasterCard, Amex), IBAN, routing numbers | + +## Managing Patterns + +To view and manage patterns within a group: + +1. Navigate to **Sensitive Data** > **Pattern Groups**. +2. Select a group to view its patterns. +3. Each pattern displays its name, regex expression, and enabled/disabled status. + +Administrators can enable or disable individual patterns within a group. Disabled patterns are excluded from scan matching. + +## Pattern Fields + +| Field | Description | +|---|---| +| **Name** | Descriptive label for the pattern | +| **Regex** | The regular expression used for matching | +| **Confidence** | Expected match accuracy (High, Medium, Low) | +| **Enabled** | Whether the pattern is active during scans | + +:::note +Changes to pattern enablement take effect on the next scan execution. Running scans use the configuration that was active at scan start time. +::: diff --git a/docs/accessanalyzer/1.0/admin/sensitivedata/taxonomygroups.md b/docs/accessanalyzer/1.0/admin/sensitivedata/taxonomygroups.md new file mode 100644 index 0000000000..ff36f4f0b9 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/sensitivedata/taxonomygroups.md @@ -0,0 +1,39 @@ +--- +title: "Taxonomy Groups and Rules" +description: "Configuring taxonomy-based data classification" +sidebar_position: 30 +--- + +# Taxonomy Groups and Rules + +Taxonomy groups map pattern detections to compliance frameworks and regulatory standards. They provide a compliance-oriented view of sensitive data findings. + +## Built-in Compliance Mappings + +Access Analyzer includes pre-configured taxonomy groups aligned to major regulatory frameworks: + +| Taxonomy Group | Framework | Relevant Data Types | +|---|---|---| +| **GDPR** | General Data Protection Regulation | PII, personal data, EU resident identifiers | +| **CCPA** | California Consumer Privacy Act | PII, consumer records, financial identifiers | +| **HIPAA** | Health Insurance Portability and Accountability Act | PHI, medical records, health plan data | +| **PCI DSS** | Payment Card Industry Data Security Standard | Credit card numbers, cardholder data | +| **GLBA** | Gramm-Leach-Bliley Act | Financial records, account numbers | +| **CMMC** | Cybersecurity Maturity Model Certification | Controlled unclassified information, credentials | + +## How Taxonomy Mapping Works + +Each taxonomy group references one or more pattern groups. When a sensitive data scan produces a match against a pattern, the finding is automatically tagged with all associated taxonomy labels. This enables compliance-focused reporting without additional configuration. + +## Managing Taxonomy Groups + +To view taxonomy group configuration: + +1. Navigate to **Sensitive Data** > **Taxonomy Groups**. +2. Select a group to view its associated patterns and compliance mappings. + +Administrators can enable or disable taxonomy groups to control which compliance labels appear in scan results. + +:::note +Built-in taxonomy groups are updated with product releases to reflect changes in regulatory standards. +::: diff --git a/docs/accessanalyzer/1.0/admin/serviceaccounts/_category_.json b/docs/accessanalyzer/1.0/admin/serviceaccounts/_category_.json new file mode 100644 index 0000000000..85d0158bb9 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/serviceaccounts/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Service Accounts", + "position": 50, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/admin/serviceaccounts/associating.md b/docs/accessanalyzer/1.0/admin/serviceaccounts/associating.md new file mode 100644 index 0000000000..cd3479356a --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/serviceaccounts/associating.md @@ -0,0 +1,42 @@ +--- +title: "Associating with Sources" +description: "Linking service accounts to data sources" +sidebar_position: 30 +--- + +# Associating with Sources + +Each data source requires an associated service account to authenticate when connecting to the target environment. A single service account can be shared across multiple sources of compatible types. + +## Assigning a Service Account to a Source + +Service accounts are assigned during source creation or by editing an existing source: + +1. Navigate to **Sources** and open the source detail view. +2. Click **Edit**. +3. In the **Service Account** field, select the desired account from the dropdown. +4. Click **Save**. + +The dropdown only shows service accounts with a credential type compatible with the selected source type. + +## Changing the Associated Account + +To switch a source to a different service account, edit the source and select a new account. The change takes effect on the next scan execution. Running scans continue to use the previously assigned account until completion. + +## Disassociating a Service Account + +To remove a service account association, edit the source and clear the **Service Account** field, then assign a replacement. Sources cannot be saved without a service account. + +:::note +Verify connectivity after changing service account associations by running a [Test Connection](/docs/accessanalyzer/1_0/admin/sources/testconnections). +::: + +## Compatibility Matrix + +| Source Type | Username/Password | OAuth2 Client Credentials | Certificate | +|---|---|---|---| +| CIFS | Yes | No | No | +| SharePoint | No | Yes | Yes | +| Active Directory | Yes | No | No | +| Entra ID | No | Yes | Yes | +| Local Groups | Yes | No | No | diff --git a/docs/accessanalyzer/1.0/admin/serviceaccounts/credentialtypes.md b/docs/accessanalyzer/1.0/admin/serviceaccounts/credentialtypes.md new file mode 100644 index 0000000000..7dc69e4b2f --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/serviceaccounts/credentialtypes.md @@ -0,0 +1,37 @@ +--- +title: "Credential Types" +description: "Supported credential types and configurations" +sidebar_position: 20 +--- + +# Credential Types + +Access Analyzer supports three credential types for service accounts. The appropriate type depends on the target source and its authentication requirements. Service accounts can be created ahead of time from the **Service Accounts** page, or inline during the Connect Source wizard. + +## Supported Types + +| Credential Type | Description | Typical Use | +|---|---|---| +| **Username/Password** | Standard username and password pair | CIFS file shares, Active Directory, Local Groups | +| **OAuth2 Client Credentials** | Client ID and client secret for OAuth2 flows | Entra ID | +| **Certificate** | X.509 certificate with private key | SharePoint Online | + +## Username/Password + +Provide a **Username** and **Password**. The password is encrypted at rest. For Active Directory and file server sources, use the `DOMAIN\username` or `username@domain.com` format. + +Used by the **File Server** and **Active Directory** wizards. During the wizard, click **+ Create New Account** to create a username/password service account inline. + +## OAuth2 Client Credentials + +Provide a **Client ID** and **Client Secret**. These credentials are used in the OAuth2 client credentials grant flow to obtain an access token from the identity provider. + +Used by the **Entra ID** wizard. The Client ID and Client Secret come from an Azure AD app registration — see [App Registration and Permissions](/docs/accessanalyzer/1_0/connectors/iam/entraid/appregistration) for setup instructions. + +## Certificate + +Upload a **Certificate** file (PEM or PFX format) and provide the **Private Key** or PFX password. Certificate-based authentication is used for SharePoint Online connections. + +:::note +Credential values are stored encrypted and cannot be viewed after creation. To update credentials, edit the service account and provide new values. +::: diff --git a/docs/accessanalyzer/1.0/admin/serviceaccounts/overview.md b/docs/accessanalyzer/1.0/admin/serviceaccounts/overview.md new file mode 100644 index 0000000000..aed048051c --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/serviceaccounts/overview.md @@ -0,0 +1,33 @@ +--- +title: "Service Accounts" +description: "Managing credentials for data source connections" +sidebar_position: 10 +--- + +# Service Accounts + +Service accounts store the credentials that Access Analyzer uses to connect to and authenticate against data sources. Each service account is configured with a specific credential type and can be associated with one or more sources. + +## Creating a Service Account + +To create a service account: + +1. Navigate to **Service Accounts** in the sidebar. +2. Click **Create Service Account**. +3. Enter a **Name** and optional **Description**. +4. Select the [credential type](/docs/accessanalyzer/1_0/admin/serviceaccounts/credentialtypes) (Username/Password, OAuth2 Client Credentials, or Certificate). +5. Provide the required credential fields. +6. Click **Save**. + +## Service Account List + +The service account list displays all configured accounts with their name, credential type, number of associated sources, and creation date. Credentials are never displayed in plaintext after initial creation. + +## Editing and Deleting + +- **Edit** -- Update the name, description, or credential values. Changing credentials takes effect on the next scan execution. +- **Delete** -- Remove a service account. This operation fails if the account is currently associated with any sources. + +:::warning +Before deleting a service account, disassociate it from all sources. See [Associating with Sources](/docs/accessanalyzer/1_0/admin/serviceaccounts/associating). +::: diff --git a/docs/accessanalyzer/1.0/admin/settings/_category_.json b/docs/accessanalyzer/1.0/admin/settings/_category_.json new file mode 100644 index 0000000000..2e922ee742 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/settings/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Application Settings", + "position": 90, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/admin/settings/featureflags.md b/docs/accessanalyzer/1.0/admin/settings/featureflags.md new file mode 100644 index 0000000000..e40dbea10d --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/settings/featureflags.md @@ -0,0 +1,48 @@ +--- +title: "Feature Flags" +description: "Runtime feature toggles and configuration" +sidebar_position: 40 +--- + +# Feature Flags + +Feature flags allow administrators to enable or disable specific application capabilities at runtime without restarting the service. Flags are defined in the `app_settings.yml` configuration file and can be overridden through the web interface. + +## Viewing Feature Flags + +Navigate to **Settings** > **Feature Flags** to see all available flags, their current state, and descriptions. + +## Configuration File + +Feature flags are declared in `app_settings.yml` on the application server: + +```yaml +feature_flags: + sensitive_data_scanning: true + identity_correlation: true + audit_log_export: true + advanced_permission_paths: false +``` + +## Overriding via the Web Interface + +To toggle a feature flag: + +1. Navigate to **Settings** > **Feature Flags**. +2. Locate the flag and toggle its state. +3. Click **Save**. + +Web interface overrides take precedence over values in `app_settings.yml`. To revert to the file-based value, click **Reset to Default** next to the flag. + +## Common Feature Flags + +| Flag | Description | +|---|---| +| `sensitive_data_scanning` | Enables or disables the sensitive data scan type | +| `identity_correlation` | Enables cross-provider identity matching in IAM | +| `audit_log_export` | Enables the audit log export functionality | +| `advanced_permission_paths` | Enables detailed permission path visualization | + +:::warning +Disabling a feature flag immediately removes the associated functionality from the web interface for all users. Running operations that depend on a disabled flag may fail. +::: diff --git a/docs/accessanalyzer/1.0/admin/settings/overview.md b/docs/accessanalyzer/1.0/admin/settings/overview.md new file mode 100644 index 0000000000..f7268f3fb5 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/settings/overview.md @@ -0,0 +1,33 @@ +--- +title: "Application Settings" +description: "Global application configuration options" +sidebar_position: 10 +--- + +# Application Settings + +The Settings section provides administrators with controls over global application behavior. Configuration changes made here affect all users and system operations. + +## Settings Categories + +| Category | Description | +|---|---| +| [Concurrent Scan Limits](/docs/accessanalyzer/1_0/admin/settings/scanlimits) | Control the maximum number of scans that can execute simultaneously | +| [Session and Token TTL](/docs/accessanalyzer/1_0/admin/settings/sessionttl) | Configure session duration and token refresh intervals | +| [Feature Flags](/docs/accessanalyzer/1_0/admin/settings/featureflags) | Enable or disable application features at runtime | + +## Accessing Settings + +Navigate to **Settings** in the sidebar. Only users with the **Administrator** role can view and modify settings. + +## Saving Changes + +After modifying a setting, click **Save** to apply the change. Most settings take effect immediately. Settings that require a service restart display a notification indicating when the change will be applied. + +:::warning +Changing application settings can affect system behavior for all users. Review changes carefully before saving, and coordinate with other administrators when modifying production configurations. +::: + +## Configuration File + +Some advanced settings are managed through the `app_settings.yml` configuration file on the server. Settings modified through the web interface override values in the configuration file. See [Feature Flags](/docs/accessanalyzer/1_0/admin/settings/featureflags) for details on file-based configuration. diff --git a/docs/accessanalyzer/1.0/admin/settings/scanlimits.md b/docs/accessanalyzer/1.0/admin/settings/scanlimits.md new file mode 100644 index 0000000000..8711666a0c --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/settings/scanlimits.md @@ -0,0 +1,37 @@ +--- +title: "Concurrent Scan Limits" +description: "Configuring maximum concurrent scan execution" +sidebar_position: 20 +--- + +# Concurrent Scan Limits + +Access Analyzer limits the number of scans that can run simultaneously to manage system resource consumption. Administrators configure these limits based on available server capacity. + +## Configuration + +To configure scan limits: + +1. Navigate to **Settings** in the sidebar. +2. Locate the **Concurrent Scan Limits** section. +3. Set the desired values and click **Save**. + +## Available Settings + +| Setting | Description | Default | +|---|---|---| +| **Max Concurrent Access Scans** | Maximum number of access scans running at the same time | 5 | +| **Max Concurrent Sensitive Data Scans** | Maximum number of sensitive data scans running at the same time | 3 | +| **Max Total Concurrent Scans** | Combined limit across all scan types | 8 | + +## Behavior When Limits Are Reached + +When a scan is triggered (manually or by schedule) and the concurrent limit has been reached, the scan enters a **Pending** state and is queued. Queued scans start automatically as running scans complete, in first-in-first-out order. + +:::note +Sensitive data scans are typically more resource-intensive than access scans. Consider setting a lower concurrent limit for sensitive data scans to avoid impacting system performance. +::: + +## Monitoring + +View the current number of running and queued scans from the **Scans** list page. The status column indicates whether each scan is **Running**, **Pending**, or **Queued**. diff --git a/docs/accessanalyzer/1.0/admin/settings/sessionttl.md b/docs/accessanalyzer/1.0/admin/settings/sessionttl.md new file mode 100644 index 0000000000..00d6f81382 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/settings/sessionttl.md @@ -0,0 +1,41 @@ +--- +title: "Session and Token TTL" +description: "Configuring session duration and token refresh intervals" +sidebar_position: 30 +--- + +# Session and Token TTL + +Session and token TTL (time-to-live) settings control how long user sessions remain valid and when tokens are refreshed. These settings balance security requirements with user convenience. + +## Configuration + +To configure session TTL: + +1. Navigate to **Settings** in the sidebar. +2. Locate the **Session Configuration** section. +3. Adjust the values and click **Save**. + +## Available Settings + +| Setting | Description | Default | +|---|---|---| +| **Session TTL** | Maximum lifetime of a session, in minutes | 480 (8 hours) | +| **Idle Timeout** | Time of inactivity before a session expires, in minutes | 60 | +| **Token Refresh Threshold** | Percentage of TTL elapsed before automatic token refresh occurs | 50% | + +## How TTL Affects Users + +- When the **Session TTL** expires, the user is logged out regardless of activity. +- When the **Idle Timeout** elapses without any API requests, the session expires. +- Active sessions are automatically refreshed when the elapsed time exceeds the **Token Refresh Threshold**, extending the session without user intervention. + +See [Token Refresh and Expiration](/docs/accessanalyzer/1_0/admin/authentication/tokenrefresh) for details on the refresh mechanism. + +:::warning +Setting very long session TTLs increases the window of exposure if a session token is compromised. Follow your organization's security policies when configuring these values. +::: + +## Session Storage + +Sessions are stored in Redis. Ensure the Redis instance has sufficient memory to accommodate all active sessions, especially in environments with many concurrent users. diff --git a/docs/accessanalyzer/1.0/admin/sources/_category_.json b/docs/accessanalyzer/1.0/admin/sources/_category_.json new file mode 100644 index 0000000000..ac24200ff0 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/sources/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Data Source Management", + "position": 40, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/admin/sources/editdelete.md b/docs/accessanalyzer/1.0/admin/sources/editdelete.md new file mode 100644 index 0000000000..41b634770e --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/sources/editdelete.md @@ -0,0 +1,40 @@ +--- +title: "Editing and Deleting Sources" +description: "Modifying and removing data sources" +sidebar_position: 40 +--- + +# Editing and Deleting Sources + +Administrators can modify source configuration or remove sources that are no longer needed. Both operations are available from the source detail view. + +## Editing a Source + +To edit a source: + +1. Navigate to **Sources** and click the target source to open its detail view. +2. Click **Edit**. +3. Update the desired fields such as connection parameters, display name, or associated service account. +4. Click **Save**. + +:::note +The source type cannot be changed after creation. To use a different type, create a new source and delete the old one. +::: + +## Deleting a Source + +To delete a source: + +1. Open the source detail view. +2. Click **Delete**. +3. Confirm the deletion in the dialog. + +:::warning +Deleting a source removes all associated scan configurations and execution history. This action cannot be undone. Export any required scan results before deleting. +::: + +## Impact on Related Resources + +- **Scans** -- Any scans targeting the deleted source are also removed. +- **Source Groups** -- The source is automatically removed from any groups it belonged to. +- **Scan Results** -- Historical scan result data associated with the source is permanently deleted. diff --git a/docs/accessanalyzer/1.0/admin/sources/overview.md b/docs/accessanalyzer/1.0/admin/sources/overview.md new file mode 100644 index 0000000000..f23e5217a5 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/sources/overview.md @@ -0,0 +1,42 @@ +--- +title: "Data Source Management" +description: "Adding and managing data sources" +sidebar_position: 10 +--- + +# Data Source Management + +Sources represent the target environments that Access Analyzer connects to for scanning. Sources are organized into **source groups** — named collections that share a service account and configuration. Administrators create, edit, test, and delete sources from the **Sources** section. + +## Adding Sources + +Sources are created through the **Connect Source** wizard, a 3-step guided workflow: + +1. Navigate to **Sources** in the sidebar. +2. Click **Connect Source** to open the wizard drawer. +3. **Step 1** — Select the [source type](/docs/accessanalyzer/1_0/admin/sources/sourcetypes) (File Server, Active Directory, Entra ID, or SharePoint). +4. **Step 2** — Name the source group, assign a [service account](/docs/accessanalyzer/1_0/admin/serviceaccounts/overview), and add one or more sources. +5. **Step 3** — Configure scan types, scan options, and scheduling. +6. Click **Complete Setup** to create the source group, sources, and scans in one operation. + +The wizard uses the `POST /v1/source-groups/setup` endpoint to create all resources atomically. + +### Source Group Behavior by Type + +| Source Type | Sources per Group | Notes | +| --- | --- | --- | +| **File Server** | Multiple | Add many servers with shared service account and domain | +| **Active Directory** | Multiple | Add multiple domain controllers | +| **Entra ID** | Single | One Azure AD tenant per group | +| **SharePoint Online** | Multiple | Add multiple site collections | + +## Source List + +The sources list displays all configured sources with their name, type, connection status, and associated service account. Use the data table controls to filter by type or search by name. + +## Related Topics + +- [Source Types and Configuration](/docs/accessanalyzer/1_0/admin/sources/sourcetypes) +- [Testing Connections](/docs/accessanalyzer/1_0/admin/sources/testconnections) +- [Editing and Deleting Sources](/docs/accessanalyzer/1_0/admin/sources/editdelete) +- [Source Groups](/docs/accessanalyzer/1_0/admin/sources/sourcegroups) diff --git a/docs/accessanalyzer/1.0/admin/sources/sourcegroups.md b/docs/accessanalyzer/1.0/admin/sources/sourcegroups.md new file mode 100644 index 0000000000..13bce1ba62 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/sources/sourcegroups.md @@ -0,0 +1,51 @@ +--- +title: "Source Groups" +description: "Organizing sources into groups with shared configuration" +sidebar_position: 50 +--- + +# Source Groups + +A source group is a named collection of related sources that share a common service account, configuration, and scan settings. Source groups are the primary organizational unit for sources in Access Analyzer. + +## How Source Groups Work + +Source groups are created through the **Connect Source** wizard, which creates the group, all its sources, and associated scans in a single atomic operation. Each source group has: + +- A **name** to identify the group +- A **source type** (all sources in the group are the same type) +- A **service account** shared by all sources in the group +- One or more **sources** (the actual connection targets) +- One or more **scans** with a shared schedule + +## Source Groups by Type + +| Source Type | Sources per Group | Example | +| --- | --- | --- | +| **File Server** | Multiple servers | `Finance File Servers` with `fs01`, `fs02`, `fs03` — all sharing one service account and domain | +| **Active Directory** | Multiple domain controllers | `Corp AD` with `dc01`, `dc02` | +| **Entra ID** | Single tenant | `Corporate Entra ID` with one Azure AD tenant | +| **SharePoint Online** | Multiple site collections | `Marketing SharePoint` with several sites | + +## Creating a Source Group + +Source groups are created exclusively through the Connect Source wizard: + +1. Navigate to **Sources** in the sidebar +2. Click **Connect Source** +3. Follow the 3-step wizard: select source type, configure sources, set up scans +4. Click **Complete Setup** + +For detailed instructions, see [Adding a Data Source](/docs/accessanalyzer/1_0/gettingstarted/firstscan/addingsource). + +## Viewing Source Groups + +The sources list displays individual sources, each showing its parent source group. You can filter by source group to see all sources within a group. + +## Deleting a Source Group + +Deleting a source group removes the group, all its sources, and all associated scans. + +:::warning +Deleting a source group is permanent and removes all sources and scan configurations within it. Scan execution history is preserved for audit purposes. +::: diff --git a/docs/accessanalyzer/1.0/admin/sources/sourcetypes.md b/docs/accessanalyzer/1.0/admin/sources/sourcetypes.md new file mode 100644 index 0000000000..55f2f7cc4d --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/sources/sourcetypes.md @@ -0,0 +1,35 @@ +--- +title: "Source Types and Configuration" +description: "Available source types and their configuration parameters" +sidebar_position: 20 +--- + +# Source Types and Configuration + +Access Analyzer supports multiple source types, each targeting a different data environment. The source type determines the required connection parameters and the kinds of scans available. + +## Available Source Types + +| Source Type | Description | Supported Scans | +|---|---|---| +| **CIFS** | Windows file shares accessed via SMB/CIFS protocol | Access, Sensitive Data | +| **SharePoint** | Microsoft SharePoint Online or on-premises sites | Access, Sensitive Data | +| **Active Directory** | On-premises Active Directory domains | Access | +| **Entra ID** | Microsoft Entra ID (formerly Azure AD) tenants | Access | +| **Local Groups** | Local user and group membership on Windows servers | Access | + +## Configuration Parameters + +Each source type requires specific connection details: + +- **CIFS** -- Server hostname or IP, share path, and port number. +- **SharePoint** -- Site URL, authentication method, and tenant ID. +- **Active Directory** -- Domain controller hostname, base DN, and LDAP port. +- **Entra ID** -- Tenant ID, client ID, and authentication secret or certificate. +- **Local Groups** -- Target server hostname or IP address. + +All source types require an associated [service account](/docs/accessanalyzer/1_0/admin/serviceaccounts/overview) with appropriate credentials for the target environment. + +:::note +Source type cannot be changed after creation. To switch types, delete the existing source and create a new one. +::: diff --git a/docs/accessanalyzer/1.0/admin/sources/testconnections.md b/docs/accessanalyzer/1.0/admin/sources/testconnections.md new file mode 100644 index 0000000000..ff5de9a3c1 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/sources/testconnections.md @@ -0,0 +1,54 @@ +--- +title: "Testing Connections" +description: "Validating source connectivity before scanning" +sidebar_position: 30 +--- + +# Testing Connections + +Before running scans, verify that Access Analyzer can reach and authenticate to each configured source using the test connection feature. Connection testing is available both during source creation (in the wizard) and on existing sources. + +## Testing During Source Creation + +The Connect Source wizard includes a **Test Connection** button in Step 2: + +- **File Server** — Tests all servers in parallel. Each server shows its own status: **Connected** (green), **Failed** (red), or **Testing** (spinner). A summary toast shows the overall result (for example, "All 3 connections successful" or "1 of 3 failed"). +- **Entra ID** — Tests the OAuth2 connection to the specified Azure AD tenant. Status appears inline: "Successfully connected to Entra ID" or "Connection failed" with an error message. +- **Active Directory** — Tests connectivity to each domain controller. + +:::note +Connection testing in the wizard is non-blocking. You can proceed to the next step regardless of test results. +::: + +## Testing Existing Sources + +To test an existing source connection: + +1. Navigate to **Sources** in the sidebar. +2. Locate the source in the list and click its row to open the detail view. +3. Click **Test Connection**. +4. Wait for the test to complete. Results appear inline. + +## What Gets Tested + +The test connection operation sends a request to `POST /v1/sources/test-connection` with the source's connection parameters. It validates: + +| Check | Description | +|---|---| +| **Network Reachability** | Confirms the target host and port are accessible from the application server | +| **Authentication** | Verifies the associated service account credentials are accepted | +| **Authorization** | Confirms the service account has sufficient permissions to read the target data | + +## Troubleshooting + +If a connection test fails: + +- Verify the source hostname, port, and path are correct. +- Confirm the service account credentials have not expired or been rotated. +- Check that network firewalls allow traffic between the Access Analyzer server and the target host. +- For Entra ID, verify the Tenant ID is correct and the app registration has the required API permissions. +- Review [System Logs](/docs/accessanalyzer/1_0/admin/systemlogs) for detailed error messages. + +:::note +Connection tests do not scan data. They only validate that the connection can be established and authenticated. +::: diff --git a/docs/accessanalyzer/1.0/admin/systemlogs.md b/docs/accessanalyzer/1.0/admin/systemlogs.md new file mode 100644 index 0000000000..383d3646d2 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/systemlogs.md @@ -0,0 +1,47 @@ +--- +title: "System Logs" +description: "Viewing and exporting system log data" +sidebar_position: 110 +--- + +# System Logs + +System logs provide visibility into the internal operations of Access Analyzer, including application events, background job processing, and error diagnostics. These logs are distinct from audit logs, which track user actions. + +## Viewing System Logs + +Navigate to **System Logs** in the sidebar to access the log viewer. System logs display application-level events including: + +- Application startup and shutdown events +- Background job execution (scan workers, identity sync) +- Connection errors and retry attempts +- API request errors and exceptions + +## Sidekiq Dashboard + +Access Analyzer uses Sidekiq for background job processing. The Sidekiq dashboard provides real-time monitoring of: + +| View | Description | +|---|---| +| **Queues** | Active job queues and their current depth | +| **Workers** | Currently executing jobs and their runtime | +| **Retries** | Failed jobs scheduled for automatic retry | +| **Dead** | Jobs that have exhausted all retry attempts | +| **Scheduled** | Jobs queued for future execution | + +Access the Sidekiq dashboard from **System Logs** > **Job Monitor**. + +## Log Levels + +System logs are categorized by severity: + +| Level | Description | +|---|---| +| **ERROR** | Failures requiring attention | +| **WARN** | Unexpected conditions that did not cause failures | +| **INFO** | Normal operational events | +| **DEBUG** | Detailed diagnostic output (disabled by default) | + +:::note +Debug-level logging generates significant output and can impact performance. Enable it only for targeted troubleshooting and disable it afterward. +::: diff --git a/docs/accessanalyzer/1.0/admin/users/_category_.json b/docs/accessanalyzer/1.0/admin/users/_category_.json new file mode 100644 index 0000000000..9633707491 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/users/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "User Management", + "position": 20, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/admin/users/overview.md b/docs/accessanalyzer/1.0/admin/users/overview.md new file mode 100644 index 0000000000..74de4204be --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/users/overview.md @@ -0,0 +1,38 @@ +--- +title: "User Management" +description: "Creating and managing user accounts" +sidebar_position: 10 +--- + +# User Management + +Access Analyzer supports multi-user access with role-based permissions. Administrators can create, edit, and deactivate user accounts from the **Users** section of the web interface. + +## Creating a User + +To create a new user: + +1. Navigate to **Users** in the sidebar. +2. Click **Create User**. +3. Enter the required fields: **Username**, **Email**, and **Password**. +4. Assign a [role](/docs/accessanalyzer/1_0/admin/users/roles) (Administrator or Viewer). +5. Click **Save**. + +Passwords are hashed using Argon2id before storage. Users must meet the configured password complexity requirements. + +## Managing Users + +From the users list, administrators can: + +- **Edit** a user to update their email, role, or password. +- **Deactivate** a user to revoke access without deleting the account record. +- **Delete** a user to permanently remove the account. + +:::warning +Deleting a user is irreversible. Consider deactivating accounts instead if you need to preserve audit history. +::: + +## Related Topics + +- [Roles and Permissions](/docs/accessanalyzer/1_0/admin/users/roles) +- [Session Management](/docs/accessanalyzer/1_0/admin/users/sessions) diff --git a/docs/accessanalyzer/1.0/admin/users/roles.md b/docs/accessanalyzer/1.0/admin/users/roles.md new file mode 100644 index 0000000000..9c83c8f400 --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/users/roles.md @@ -0,0 +1,36 @@ +--- +title: "Roles and Permissions" +description: "Admin and Viewer role definitions and access levels" +sidebar_position: 20 +--- + +# Roles and Permissions + +Access Analyzer uses a role-based access control model with two built-in roles. Each user is assigned exactly one role at account creation, which determines their access level throughout the application. + +## Role Definitions + +| Capability | Administrator | Viewer | +|---|---|---| +| View dashboards and reports | Yes | Yes | +| View sources, scans, and results | Yes | Yes | +| Create, edit, and delete sources | Yes | No | +| Create, schedule, and run scans | Yes | No | +| Manage service accounts | Yes | No | +| Configure sensitive data rules | Yes | No | +| Manage users and roles | Yes | No | +| Modify application settings | Yes | No | +| View audit logs | Yes | Yes | +| Export audit logs | Yes | No | + +## Administrator + +The **Administrator** role grants full access to all features, including user management, source configuration, scan execution, settings, and audit log exports. At least one administrator account must exist in the system. + +## Viewer + +The **Viewer** role provides read-only access to dashboards, scan results, source listings, and audit logs. Viewers cannot create, modify, or delete any resources. + +:::note +Role assignments can be changed at any time by an administrator through the user edit form. +::: diff --git a/docs/accessanalyzer/1.0/admin/users/sessions.md b/docs/accessanalyzer/1.0/admin/users/sessions.md new file mode 100644 index 0000000000..7af8472d7f --- /dev/null +++ b/docs/accessanalyzer/1.0/admin/users/sessions.md @@ -0,0 +1,35 @@ +--- +title: "Session Management" +description: "Viewing and managing active user sessions" +sidebar_position: 30 +--- + +# Session Management + +Access Analyzer maintains session state for all authenticated users using Redis-backed server-side sessions. Administrators can view and manage active sessions from the **Users** section. + +## Viewing Active Sessions + +Navigate to **Users** > **Sessions** to see a list of all active sessions. The table displays: + +| Column | Description | +|---|---| +| **User** | The username associated with the session | +| **IP Address** | The client IP from which the session was created | +| **Created At** | Timestamp when the session was initiated | +| **Last Active** | Timestamp of the most recent request | +| **Expires At** | When the session will automatically expire based on the configured TTL | + +## Revoking Sessions + +To revoke a session, select the target row and click **Revoke**. The user will be immediately logged out and must re-authenticate. Administrators can also revoke all sessions for a specific user from the user detail page. + +## Session Security + +- Sessions are validated against the originating IP address. If the client IP changes, the session is invalidated. +- Session TTL is configurable in [Settings](/docs/accessanalyzer/1_0/admin/settings/sessionttl). +- Idle sessions expire automatically after the configured timeout period. + +:::warning +Revoking a session takes effect immediately. The affected user will lose access to any in-progress work that has not been saved. +::: diff --git a/docs/accessanalyzer/1.0/connectors/_category_.json b/docs/accessanalyzer/1.0/connectors/_category_.json new file mode 100644 index 0000000000..f7b8ad38d7 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Connectors", + "position": 60, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/connectors/iam/_category_.json b/docs/accessanalyzer/1.0/connectors/iam/_category_.json new file mode 100644 index 0000000000..47506a72c8 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/iam/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "IAM Connectors", + "position": 10, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/connectors/iam/activedirectory/_category_.json b/docs/accessanalyzer/1.0/connectors/iam/activedirectory/_category_.json new file mode 100644 index 0000000000..365d3210fe --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/iam/activedirectory/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Active Directory", + "position": 10, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "connectionsetup" + } +} diff --git a/docs/accessanalyzer/1.0/connectors/iam/activedirectory/connectionsetup.md b/docs/accessanalyzer/1.0/connectors/iam/activedirectory/connectionsetup.md new file mode 100644 index 0000000000..3dbcd27070 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/iam/activedirectory/connectionsetup.md @@ -0,0 +1,47 @@ +--- +title: "Connection Setup" +description: "Configuring the Active Directory LDAP connection" +sidebar_position: 10 +--- + +# Connection Setup + +Configure the Active Directory connector to synchronize users and groups from your on-premises directory. + +## Prerequisites + +- A domain service account with read access to directory objects — see [Active Directory Requirements](/docs/accessanalyzer/1_0/requirements/connectors/activedirectory) +- Network connectivity from the Access Analyzer VM to a domain controller on port 389 (LDAP) or 636 (LDAPS) + +## Create a Service Account + +1. Navigate to **Service Accounts** in the sidebar +2. Click **Add Service Account** +3. Enter a **Name** (for example, `AD Read-Only Service Account`) +4. Select **Username/Password** as the type +5. Enter the **Username** in `DOMAIN\username` or `user@domain.com` format +6. Enter the **Password** +7. Click **Add service account** + +## Add Active Directory as a Source + +1. Navigate to **Configuration** > **Sources** +2. Click **Add Source** +3. Select **IAM Source** as the category +4. Select **Active Directory** as the source type +5. Select the service account created above +6. Enter the **Host** (domain controller hostname or IP) +7. Enter the **Port** (`389` for LDAP, `636` for LDAPS) +8. Enter the **Domain** (for example, `corp.example.com`) +9. Click **Test Connection** to verify connectivity +10. After a successful test, click **Create Source** + +## Test Connection + +The test connection validates: + +- Network connectivity to the domain controller +- LDAP bind with the provided credentials +- Ability to query directory objects + +If the test fails, verify the domain controller is reachable on the specified port and the credentials are correct. diff --git a/docs/accessanalyzer/1.0/connectors/iam/activedirectory/customattributes.md b/docs/accessanalyzer/1.0/connectors/iam/activedirectory/customattributes.md new file mode 100644 index 0000000000..fb620e0bb8 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/iam/activedirectory/customattributes.md @@ -0,0 +1,12 @@ +--- +title: "Custom Attributes" +description: "Collecting custom LDAP attributes" +sidebar_position: 40 +draft: true +--- + +# Custom Attributes + +:::note +Custom LDAP attribute collection is planned for a future release of Access Analyzer. This page will be updated when the feature becomes available. +::: diff --git a/docs/accessanalyzer/1.0/connectors/iam/activedirectory/groupmembership.md b/docs/accessanalyzer/1.0/connectors/iam/activedirectory/groupmembership.md new file mode 100644 index 0000000000..397959033f --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/iam/activedirectory/groupmembership.md @@ -0,0 +1,26 @@ +--- +title: "Group Membership Mapping" +description: "Transitive group membership resolution" +sidebar_position: 30 +--- + +# Group Membership Mapping + +Access Analyzer resolves transitive (nested) group memberships to build a complete picture of effective access. + +## How It Works + +The Active Directory connector collects: + +1. **Direct memberships** — Users and groups that are immediate members of a group +2. **Nested memberships** — Groups that are members of other groups, creating a hierarchy + +Access Analyzer flattens these hierarchies to determine **effective membership** — the complete list of groups a user belongs to, whether directly or through nesting. + +## Impact on Access Analysis + +Effective group memberships are mapped to entitlements discovered by source connector scans, enabling Access Analyzer to show: + +- All groups that grant a user access to a resource +- Whether access comes from direct or nested group membership +- Overly permissive access through deeply nested group chains diff --git a/docs/accessanalyzer/1.0/connectors/iam/activedirectory/usergroupsync.md b/docs/accessanalyzer/1.0/connectors/iam/activedirectory/usergroupsync.md new file mode 100644 index 0000000000..3be2c6e33e --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/iam/activedirectory/usergroupsync.md @@ -0,0 +1,30 @@ +--- +title: "User and Group Sync" +description: "Synchronizing users and groups from Active Directory" +sidebar_position: 20 +--- + +# User and Group Sync + +The Active Directory connector performs a full synchronization of users, groups, and group memberships. + +## What Gets Synchronized + +| Object Type | Data Collected | +| --- | --- | +| **Users** | Display name, SAM account name, UPN, email, distinguished name, enabled status | +| **Groups** | Group name, type (security/distribution), scope (domain local/global/universal), distinguished name | +| **Group memberships** | Direct and nested membership relationships | + +## Running a Sync + +1. Navigate to **Configuration** > **Scans** +2. Create or select a scan configured for the Active Directory source +3. Run the scan — the connector performs a full sync on each execution + +## Sync Behavior + +- Each sync is a **full synchronization** — all users, groups, and memberships are collected +- The connector uses LDAP3 for directory queries +- Duration depends on directory size (number of users and groups) +- Results are stored in the Access Analyzer database and used for identity-to-entitlement mapping diff --git a/docs/accessanalyzer/1.0/connectors/iam/entraid/_category_.json b/docs/accessanalyzer/1.0/connectors/iam/entraid/_category_.json new file mode 100644 index 0000000000..d1dd3ba163 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/iam/entraid/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Entra ID", + "position": 20, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "appregistration" + } +} diff --git a/docs/accessanalyzer/1.0/connectors/iam/entraid/appregistration.md b/docs/accessanalyzer/1.0/connectors/iam/entraid/appregistration.md new file mode 100644 index 0000000000..cdc2d7edef --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/iam/entraid/appregistration.md @@ -0,0 +1,74 @@ +--- +title: "App Registration and Permissions" +description: "Azure AD app registration and API permissions for Entra ID" +sidebar_position: 10 +--- + +# App Registration and Permissions + +The Entra ID connector uses an Azure AD app registration with OAuth2 client credentials for authentication. You need to create an app registration in Azure and then add its credentials as a service account in Access Analyzer. + +## Create an App Registration + +1. Sign in to the [Azure portal](https://portal.azure.com) +2. Navigate to **Microsoft Entra ID** > **App registrations** +3. Click **New registration** +4. Enter a name (for example, `Netwrix Access Analyzer - Entra ID`) +5. Leave the redirect URI blank +6. Click **Register** + +## Configure API Permissions + +1. In the app registration, go to **API permissions** +2. Click **Add a permission** > **Microsoft Graph** > **Application permissions** +3. Add the following permissions: + - `User.Read.All` + - `Group.Read.All` +4. Click **Grant admin consent** for the permissions + +## Create a Client Secret + +1. Go to **Certificates & secrets** +2. Click **New client secret** +3. Enter a description and expiration period +4. Click **Add** +5. Copy the **Value** immediately — it is not shown again + +## Add Entra ID as a Source in Access Analyzer + +Entra ID sources are created through the **Connect Source** wizard, which guides you through a 3-step process: + +### Step 1 — Select Source Type + +1. Navigate to **Configuration** > **Sources** in Access Analyzer +2. Click **Connect Source** to open the wizard drawer +3. Select **Entra ID** from the source type cards +4. Click **Next** + +### Step 2 — Configure Entra ID + +1. Enter a **Source Group Name** (for example, `Corporate Entra ID`) +2. Select or create a **Service Account**: + - Click **+ Create New Account** to add a new Entra ID service account + - Enter the **Client ID** (Application ID from Azure) and **Client Secret** + - Or select an existing Entra ID service account from the dropdown +3. Enter the **Tenant ID** — this is the Azure AD directory ID in UUID format (for example, `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`) +4. Optionally click **Test Connection** to verify OAuth2 authentication + +:::note +The test connection validates that Access Analyzer can authenticate to the Microsoft Graph API with the provided credentials. Testing is optional — you can proceed without testing. +::: + +### Step 3 — Set Up a Scan + +1. The **Users, Groups and Roles** scan is automatically enabled (cannot be disabled) +2. Configure any additional sync options (for example, **Sync Sensitivity Labels**) +3. Choose when to run the first scan: now, at a scheduled time, or on a recurring schedule +4. Click **Complete Setup** + +After setup, the source group is created and the scan runs according to your selected schedule. + +## Related Topics + +- [User and Group Sync](/docs/accessanalyzer/1_0/connectors/iam/entraid/usergroupsync) — What data is synchronized +- [Entra ID Requirements](/docs/accessanalyzer/1_0/requirements/connectors/entraid) — Permissions and prerequisites diff --git a/docs/accessanalyzer/1.0/connectors/iam/entraid/certificateauth.md b/docs/accessanalyzer/1.0/connectors/iam/entraid/certificateauth.md new file mode 100644 index 0000000000..a92d6d15ab --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/iam/entraid/certificateauth.md @@ -0,0 +1,12 @@ +--- +title: "Certificate-Based Authentication" +description: "Configuring certificate authentication for Entra ID" +sidebar_position: 30 +draft: true +--- + +# Certificate-Based Authentication + +:::note +Certificate-based authentication for Entra ID is planned for a future release. In v1.0, the Entra ID connector uses OAuth2 client credentials (client secret) authentication. See [App Registration and Permissions](/docs/accessanalyzer/1_0/connectors/iam/entraid/appregistration). +::: diff --git a/docs/accessanalyzer/1.0/connectors/iam/entraid/usergroupsync.md b/docs/accessanalyzer/1.0/connectors/iam/entraid/usergroupsync.md new file mode 100644 index 0000000000..73f1d48a42 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/iam/entraid/usergroupsync.md @@ -0,0 +1,47 @@ +--- +title: "User and Group Sync" +description: "Synchronizing users, groups, and roles from Entra ID" +sidebar_position: 20 +--- + +# User and Group Sync + +The Entra ID connector synchronizes users, groups, and roles from your Azure AD tenant into Access Analyzer. This data is used for identity mapping and entitlement analysis across your data sources. + +## What Gets Synchronized + +| Data | Description | +| --- | --- | +| **Users** | All user accounts in the tenant, including display name, UPN, and account status | +| **Groups** | Security groups and Microsoft 365 groups, including membership | +| **Roles** | Directory roles assigned to users and groups | +| **Sensitivity Labels** | Microsoft Purview sensitivity labels (optional — see [Sync Options](#sync-options) below) | + +## How It Works + +When you create an Entra ID source group through the [Connect Source wizard](/docs/accessanalyzer/1_0/gettingstarted/firstscan/addingsource), a **Users, Groups and Roles** scan is automatically configured. This scan is always enabled and cannot be disabled — it runs every time the Entra ID source is scanned. + +The connector authenticates using OAuth2 client credentials and calls the Microsoft Graph API to retrieve identity data from the specified tenant. + +## Sync Options + +During scan setup (Step 3 of the wizard), additional sync options may be available depending on the source type metadata configured on the backend. For example: + +- **Sync Sensitivity Labels** — When enabled, the connector also retrieves Microsoft Purview sensitivity labels assigned to users and groups + +These options appear as toggle switches below the scan type selector on the scan setup page. + +## Scan Scheduling + +The Users, Groups and Roles scan supports three scheduling modes: + +| Mode | Description | +| --- | --- | +| **Run scan now** | Execute immediately after setup completes | +| **Run scan at** | Schedule for a specific date and time | +| **Advanced scheduling** | Configure a recurring cron schedule | + +## Related Topics + +- [App Registration and Permissions](/docs/accessanalyzer/1_0/connectors/iam/entraid/appregistration) — Azure AD setup requirements +- [Entra ID Requirements](/docs/accessanalyzer/1_0/requirements/connectors/entraid) — Permissions and prerequisites diff --git a/docs/accessanalyzer/1.0/connectors/iam/localgroups/_category_.json b/docs/accessanalyzer/1.0/connectors/iam/localgroups/_category_.json new file mode 100644 index 0000000000..19a04b0aec --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/iam/localgroups/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Local Groups", + "position": 30, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "powershellsetup" + } +} diff --git a/docs/accessanalyzer/1.0/connectors/iam/localgroups/powershellsetup.md b/docs/accessanalyzer/1.0/connectors/iam/localgroups/powershellsetup.md new file mode 100644 index 0000000000..0144b61557 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/iam/localgroups/powershellsetup.md @@ -0,0 +1,52 @@ +--- +title: "PowerShell Remoting Setup" +description: "Configuring WinRM and PowerShell Remoting for Local Groups collection" +sidebar_position: 10 +--- + +# PowerShell Remoting Setup + +The Local Groups connector uses PowerShell Remoting (WinRM) to enumerate local users and groups on Windows machines. + +## Prerequisites + +- WinRM must be enabled on each target machine +- A service account with local administrator access or membership in the Remote Management Users group +- Network connectivity from Access Analyzer to target machines on port 5985 (HTTP) or 5986 (HTTPS) + +## Enable WinRM on Target Machines + +### Single Machine + +Run the following command in an elevated PowerShell prompt: + +```powershell +Enable-PSRemoting -Force +``` + +### Domain-Wide via Group Policy + +1. Open **Group Policy Management** +2. Navigate to **Computer Configuration** > **Administrative Templates** > **Windows Components** > **Windows Remote Management (WinRM)** > **WinRM Service** +3. Enable **Allow remote server management through WinRM** +4. Set the IPv4/IPv6 filter to `*` or specific IP ranges + +## Create a Service Account + +1. Navigate to **Service Accounts** in Access Analyzer +2. Click **Add Service Account** +3. Enter a **Name** (for example, `Local Groups - WinRM`) +4. Select **Username/Password** as the type +5. Enter the **Username** in `MACHINE\username` or `DOMAIN\username` format +6. Enter the **Password** +7. Click **Add service account** + +## Add Local Groups as a Source + +1. Navigate to **Configuration** > **Sources** +2. Click **Add Source** > **IAM Source** > **Local Groups** +3. Select the service account +4. Enter the **Host** (target machine hostname or IP) +5. Enter the **Port** (`5985` for HTTP, `5986` for HTTPS) +6. Click **Test Connection** +7. Click **Create Source** diff --git a/docs/accessanalyzer/1.0/connectors/iam/localgroups/usergroupcollection.md b/docs/accessanalyzer/1.0/connectors/iam/localgroups/usergroupcollection.md new file mode 100644 index 0000000000..2fed900d2b --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/iam/localgroups/usergroupcollection.md @@ -0,0 +1,40 @@ +--- +title: "Local User and Group Collection" +description: "Collecting local users and groups from target machines" +sidebar_position: 20 +--- + +# Local User and Group Collection + +The Local Groups connector collects local users, local groups, and group memberships from Windows machines via PowerShell Remoting. + +## What Gets Collected + +| Object Type | Data Collected | +| --- | --- | +| **Local users** | Username, full name, description, enabled status, last logon | +| **Local groups** | Group name, description, type | +| **Group memberships** | Local group members (local users and domain accounts/groups) | + +## Running a Sync + +1. Navigate to **Configuration** > **Scans** +2. Create or select a scan configured for the Local Groups source +3. Run the scan — the connector performs a sync on each execution + +## How It Works + +The connector: + +1. Establishes a WinRM session to the target machine +2. Executes PowerShell commands to enumerate local users and groups +3. Collects group membership information, including domain accounts that are members of local groups +4. Returns results to the Core API for storage and analysis + +## Use Cases + +Local group collection is useful for: + +- Identifying domain accounts with local administrator access +- Mapping local group memberships that grant file share permissions +- Detecting overly permissive local group configurations diff --git a/docs/accessanalyzer/1.0/connectors/iam/overview.md b/docs/accessanalyzer/1.0/connectors/iam/overview.md new file mode 100644 index 0000000000..e0f373519b --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/iam/overview.md @@ -0,0 +1,21 @@ +--- +title: "IAM Connectors" +description: "Identity and access management connectors" +sidebar_position: 1 +--- + +# IAM Connectors + +IAM (Identity and Access Management) connectors synchronize identity data — users, groups, and group memberships — from identity providers into Access Analyzer. This data is used to map who has access to what across your data sources. + +## Available IAM Connectors + +| Connector | Identity Provider | Operations | Credential Type | +| --- | --- | --- | --- | +| [Active Directory](/docs/accessanalyzer/1_0/connectors/iam/activedirectory/connectionsetup) | On-premises AD | Test connection, Full sync | Username / Password | +| [Entra ID](/docs/accessanalyzer/1_0/connectors/iam/entraid/appregistration) | Microsoft Entra ID | Test connection only | OAuth2 Client Credentials | +| [Local Groups](/docs/accessanalyzer/1_0/connectors/iam/localgroups/powershellsetup) | Windows local accounts | Test connection, Sync | Username / Password | + +:::note +The Entra ID connector in v1.0 supports test connection only. Full identity synchronization will be available in a future release. +::: diff --git a/docs/accessanalyzer/1.0/connectors/overview.md b/docs/accessanalyzer/1.0/connectors/overview.md new file mode 100644 index 0000000000..e3c68accb8 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/overview.md @@ -0,0 +1,42 @@ +--- +title: "Connectors" +description: "Connector architecture, types, and lifecycle" +sidebar_position: 1 +--- + +# Connectors + +Connectors are the components that communicate with external data sources and identity providers on behalf of Access Analyzer. Each connector handles authentication, data collection, and state management for its target system. + +## Connector Types + +| Category | Purpose | Connectors | +| --- | --- | --- | +| **IAM Connectors** | Synchronize identities (users, groups, memberships) from identity providers | [Active Directory](/docs/accessanalyzer/1_0/connectors/iam/activedirectory/connectionsetup), [Entra ID](/docs/accessanalyzer/1_0/connectors/iam/entraid/appregistration), [Local Groups](/docs/accessanalyzer/1_0/connectors/iam/localgroups/powershellsetup) | +| **Source Connectors** | Scan data repositories for files, permissions, and content | [CIFS/SMB](/docs/accessanalyzer/1_0/connectors/source/cifs/connectionconfig), [SharePoint Online](/docs/accessanalyzer/1_0/connectors/source/sharepointonline/connectionconfig) | + +## Connector Operations + +| Operation | Description | +| --- | --- | +| **Test connection** | Validates credentials and network connectivity | +| **Access scan** | Enumerates files, folders, and permissions on a data source | +| **Sync** | Synchronizes users, groups, and memberships from an identity provider | +| **Get object** | Retrieves specific objects or metadata from the target system | + +## Connector Execution + +Connectors run as Kubernetes Jobs managed by the Connector API. When a scan or sync is triggered: + +1. The Core API creates a scan execution record +2. The Connector API launches a Kubernetes Job with the appropriate connector +3. The connector authenticates using the associated service account +4. Data is collected and sent back to the Core API for processing +5. The job completes and reports its final status + +## State Management + +| Connector | Pause/Resume | +| --- | --- | +| CIFS/SMB | Supported | +| All others | Not supported | diff --git a/docs/accessanalyzer/1.0/connectors/source/_category_.json b/docs/accessanalyzer/1.0/connectors/source/_category_.json new file mode 100644 index 0000000000..895acef0a9 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/source/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Source Connectors", + "position": 20, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/connectors/source/cifs/_category_.json b/docs/accessanalyzer/1.0/connectors/source/cifs/_category_.json new file mode 100644 index 0000000000..6e8930174e --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/source/cifs/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "CIFS / SMB File Shares", + "position": 10, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "connectionconfig" + } +} diff --git a/docs/accessanalyzer/1.0/connectors/source/cifs/connectionconfig.md b/docs/accessanalyzer/1.0/connectors/source/cifs/connectionconfig.md new file mode 100644 index 0000000000..433e9c371a --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/source/cifs/connectionconfig.md @@ -0,0 +1,79 @@ +--- +title: "Connection Configuration" +description: "Configuring CIFS/SMB connection parameters" +sidebar_position: 10 +--- + +# Connection Configuration + +Configure the CIFS/SMB connector to scan Windows file shares for files, folders, and access permissions. File server sources are created through the **Connect Source** wizard, which supports adding multiple servers in a single source group. + +## Prerequisites + +- A service account with read access to target shares — see [CIFS Requirements](/docs/accessanalyzer/1_0/requirements/connectors/cifs) +- Network connectivity from Access Analyzer to each file server on port 445 + +## Creating a File Server Source Group + +File server sources are created through the 3-step **Connect Source** wizard: + +### Step 1 — Select Source Type + +1. Navigate to **Configuration** > **Sources** +2. Click **Connect Source** to open the wizard drawer +3. Select **File Server** from the source type cards +4. Click **Next** + +### Step 2 — Configure File Server + +1. Enter a **Source Group Name** (for example, `Finance File Servers`) +2. Select or create a **Service Account**: + - Click **+ Create New Account** to add a new username/password account + - Or select an existing service account from the dropdown +3. Optionally enter a **Domain** name (for example, `company.local`). The domain is applied to all servers in the group. + +### Adding File Servers + +Click **+ Add** or click the empty state area to begin adding servers: + +1. Select **Add Manually** (CSV import is planned for a future release) +2. In the manual entry form, enter one or more server names or IP addresses: + - Type multiple entries separated by commas, or press **Enter** after each one + - For example: `fs01, fs02, fs03` +3. Set the **Port** (default: `445`) +4. Click **Add [N] file servers** +5. Review the added servers in the table — server names are editable inline +6. Click **Done** to return to the configuration screen + +The file servers table shows each server's name, connection status, and a delete button. + +### Test Connection + +After adding servers and selecting a service account: + +1. Click **Test Connection** +2. All servers are tested in parallel +3. Each server shows its status: **Connected** (green), **Failed** (red), or **Testing** (spinner) +4. A summary toast displays the results (for example, "All 3 connections successful" or "1 of 3 failed") + +:::note +Testing is optional and non-blocking — you can proceed to the next step regardless of test results. +::: + +### Connection Parameters + +Each file server in the group uses the following connection parameters: + +| Parameter | Description | Default | +| --- | --- | --- | +| **Host** | File server hostname or IP address | — | +| **Port** | SMB port | `445` | +| **Domain** | Domain name (set at the group level) | — | + +## Supported Protocols + +The connector supports SMBv2 and SMBv3. SMBv1 is not supported due to security vulnerabilities. + +## Next Steps + +After configuring servers, click **Next** to proceed to [scan setup](/docs/accessanalyzer/1_0/gettingstarted/firstscan/configuringscan), where you configure access scan options, share filtering, and scheduling. diff --git a/docs/accessanalyzer/1.0/connectors/source/cifs/filevssharelevel.md b/docs/accessanalyzer/1.0/connectors/source/cifs/filevssharelevel.md new file mode 100644 index 0000000000..e3e596a606 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/source/cifs/filevssharelevel.md @@ -0,0 +1,53 @@ +--- +title: "File-Level vs Share-Level Permissions" +description: "Understanding file-level and share-level permission scanning" +sidebar_position: 50 +--- + +# File-Level vs Share-Level Permissions + +Windows file shares have two layers of access control: **share-level permissions** and **NTFS file-level permissions**. The effective access for a user is the most restrictive combination of both. + +## Share-Level Permissions + +Share-level permissions are set on the share itself and apply to all network access: + +- **Read** — View files and subfolders +- **Change** — Read, add, modify, and delete files +- **Full Control** — All Change permissions plus the ability to modify share permissions + +## NTFS File-Level Permissions + +NTFS permissions are set on individual files and folders and provide granular control: + +- **Read** — View file contents and attributes +- **Write** — Create files and write data +- **Modify** — Read, write, and delete +- **Full Control** — All permissions including permission changes and ownership + +## Effective Access + +The effective access for a user connecting over the network is determined by the **intersection** (most restrictive) of share-level and NTFS permissions. + +For example: +- Share permission: **Full Control** +- NTFS permission: **Read** +- Effective access: **Read** + +## Enabling File-Level Permission Scanning + +By default, Access Analyzer scans share-level permissions only. To include file-level (NTFS) permission data: + +1. During source group creation, proceed to Step 3 (scan setup) +2. Enable the **Access** scan type +3. In the access scan options, check **Include file-level permission data in scan results** + +When enabled, the connector reads the NTFS security descriptor for each file and folder in addition to the share-level ACL. This provides more detailed access path analysis but increases scan duration. + +:::note +File-level permission scanning is disabled by default because it significantly increases scan time on large file servers. Enable it when you need detailed per-file permission analysis. +::: + +## What Access Analyzer Scans + +The CIFS/SMB connector collects NTFS permissions at the file and folder level. Combined with share-level permission data, Access Analyzer reports the effective access path from user to file. diff --git a/docs/accessanalyzer/1.0/connectors/source/cifs/ntfspermissions.md b/docs/accessanalyzer/1.0/connectors/source/cifs/ntfspermissions.md new file mode 100644 index 0000000000..6b14bc1b67 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/source/cifs/ntfspermissions.md @@ -0,0 +1,33 @@ +--- +title: "NTFS Permission Scanning" +description: "Scanning NTFS access control lists" +sidebar_position: 30 +--- + +# NTFS Permission Scanning + +The CIFS/SMB connector reads NTFS access control lists (ACLs) on files and folders to identify who has access and what level of access they hold. + +## What Gets Collected + +| Data | Description | +| --- | --- | +| **ACL entries** | Each access control entry (ACE) on a file or folder, including the principal (user or group), access type (allow/deny), and permission level | +| **Permission types** | Read, Write, Modify, Full Control, and other standard NTFS permissions | +| **Inheritance** | Whether permissions are inherited from a parent folder or explicitly set | +| **Owner** | The owner of each file or folder | + +## How It Works + +1. The connector traverses the folder hierarchy on each share +2. For each file and folder, it reads the NTFS security descriptor +3. ACL entries are parsed and stored in the Access Analyzer database +4. Identities referenced in ACLs are matched to synced identities from IAM connectors + +## Access Path Analysis + +By combining NTFS permissions with identity data from Active Directory or Local Groups, Access Analyzer builds **access paths** that show: + +- Which users and groups have access to each file or folder +- Whether access is granted directly or through nested group membership +- Which permissions are explicitly set versus inherited diff --git a/docs/accessanalyzer/1.0/connectors/source/cifs/scandepthworkers.md b/docs/accessanalyzer/1.0/connectors/source/cifs/scandepthworkers.md new file mode 100644 index 0000000000..b83787d563 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/source/cifs/scandepthworkers.md @@ -0,0 +1,54 @@ +--- +title: "Scan Depth and Worker Configuration" +description: "Configuring recursion depth and concurrent workers" +sidebar_position: 40 +--- + +# Scan Depth and Worker Configuration + +The CIFS/SMB connector supports configurable scan depth and concurrent worker threads to balance thoroughness with performance. These settings are configured in Step 3 (scan setup) of the Connect Source wizard when the **Access** scan option is enabled. + +## Scan Depth + +Scan depth controls how many levels of subdirectories the connector traverses within each share. + +| Setting | Description | +| --- | --- | +| **Default** | 50 levels deep | +| **Custom** | Set to any positive integer | + +The default depth of 50 covers the vast majority of file server hierarchies. Increase this value only if your environment has deeply nested folder structures that exceed 50 levels. + +:::note +Setting scan depth to a very high number does not significantly impact performance if the actual folder hierarchy is shallower — the connector stops when there are no more subdirectories to traverse. +::: + +## Worker Threads + +Worker threads control how many directories are scanned concurrently. More threads mean faster scans but higher load on the file server. + +| Setting | Description | +| --- | --- | +| **Default** | 3 concurrent workers | +| **Range** | 1 to 20 workers | + +Guidelines for choosing a worker count: + +| Workers | Use Case | +| --- | --- | +| **1–3** | Conservative scanning with minimal file server impact (default) | +| **5–10** | Balanced performance for most environments | +| **10–20** | Maximum parallelism for large file servers with high I/O capacity | + +:::warning +Increasing worker count improves scan speed but also increases load on the file server. Start with the default of 3 and increase gradually based on file server capacity and observed scan duration. +::: + +## Configuration Location + +Both settings are found in the **Access scan options** section of the scan setup step, which appears when the **Access** scan type is enabled during source group creation. + +## Related Topics + +- [Share Enumeration and Filtering](/docs/accessanalyzer/1_0/connectors/source/cifs/shareenumeration) — Controlling which shares are scanned +- [File-Level vs Share-Level Permissions](/docs/accessanalyzer/1_0/connectors/source/cifs/filevssharelevel) — Permission scanning granularity diff --git a/docs/accessanalyzer/1.0/connectors/source/cifs/shareenumeration.md b/docs/accessanalyzer/1.0/connectors/source/cifs/shareenumeration.md new file mode 100644 index 0000000000..9bcb80a771 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/source/cifs/shareenumeration.md @@ -0,0 +1,53 @@ +--- +title: "Share Enumeration and Filtering" +description: "Discovering and filtering network shares" +sidebar_position: 20 +--- + +# Share Enumeration and Filtering + +When scanning a CIFS/SMB source, the connector discovers all available shares on the target file server. You can include or exclude specific shares, and optionally enumerate hidden shares. + +## How Share Discovery Works + +The connector enumerates all SMB shares exposed by the file server. Each share is listed with its name and path. + +## Share Filtering + +Share filtering is configured in Step 3 (scan setup) of the Connect Source wizard when the **Access** scan option is enabled. Two filtering controls are available: + +### Include Shares + +Control which shares are scanned: + +| Mode | Behavior | +| --- | --- | +| **All shares** (default) | Scan every discovered share on the file server | +| **Custom selection** | Only scan shares you explicitly specify | + +When **Custom selection** is chosen, a text field appears where you enter share names separated by commas (for example, `share1, share2, share3`). + +### Exclude Shares + +Optionally specify shares to skip during scanning. Enter share names separated by commas in the exclude field (for example, `admin$, ipc$`). Excluded shares are never scanned, even if they match the include filter. + +## Hidden Shares + +Windows hidden shares (shares whose names end with `$`) are not enumerated by default. You can enable automatic discovery of hidden shares: + +1. In the scan setup step, check **Automatically enumerate and scan hidden shares** +2. When enabled, the connector discovers and scans hidden shares alongside regular shares +3. A predefined list of default exclusions is applied automatically + +### Excluding Hidden Shares + +When hidden share collection is enabled, an additional **Exclude Hidden Shares** field appears. Enter hidden share names to exclude from auto-enumeration (for example, `ADMIN$, C$, IPC$`). + +:::info +Filtering shares reduces scan duration and focuses results on the most relevant data repositories. Exclude administrative shares (like `ADMIN$` and `IPC$`) unless you specifically need to audit their permissions. +::: + +## Related Topics + +- [Connection Configuration](/docs/accessanalyzer/1_0/connectors/source/cifs/connectionconfig) — Setting up file server connections +- [Scan Depth and Worker Configuration](/docs/accessanalyzer/1_0/connectors/source/cifs/scandepthworkers) — Controlling scan thoroughness diff --git a/docs/accessanalyzer/1.0/connectors/source/overview.md b/docs/accessanalyzer/1.0/connectors/source/overview.md new file mode 100644 index 0000000000..90620d8484 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/source/overview.md @@ -0,0 +1,23 @@ +--- +title: "Source Connectors" +description: "Data source connectors for file and cloud scanning" +sidebar_position: 1 +--- + +# Source Connectors + +Source connectors scan data repositories to discover files, folders, access permissions, and content. Results are used to identify overly permissive access and detect sensitive data. + +## Available Source Connectors + +| Connector | Data Source | Operations | Credential Type | +| --- | --- | --- | --- | +| [CIFS / SMB](/docs/accessanalyzer/1_0/connectors/source/cifs/connectionconfig) | Windows file shares | Test connection, Access scan, Get object | Username / Password | +| [SharePoint Online](/docs/accessanalyzer/1_0/connectors/source/sharepointonline/connectionconfig) | SharePoint Online sites | Test connection, Access scan, Get object | Certificate | + +## Scan Types + +| Scan Type | Description | +| --- | --- | +| **Access scan** | Enumerates file structure and access permissions | +| **Sensitive data scan** | Classifies file content against detection patterns | diff --git a/docs/accessanalyzer/1.0/connectors/source/sharepointonline/_category_.json b/docs/accessanalyzer/1.0/connectors/source/sharepointonline/_category_.json new file mode 100644 index 0000000000..4646f7123f --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/source/sharepointonline/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "SharePoint Online", + "position": 20, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "connectionconfig" + } +} diff --git a/docs/accessanalyzer/1.0/connectors/source/sharepointonline/connectionconfig.md b/docs/accessanalyzer/1.0/connectors/source/sharepointonline/connectionconfig.md new file mode 100644 index 0000000000..90bd541e78 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/source/sharepointonline/connectionconfig.md @@ -0,0 +1,44 @@ +--- +title: "Connection Configuration" +description: "Configuring SharePoint Online connection parameters" +sidebar_position: 10 +--- + +# Connection Configuration + +Configure the SharePoint Online connector to scan SharePoint sites using the Microsoft Graph API with certificate-based authentication. + +## Prerequisites + +- An Azure AD app registration with `Sites.Read.All` permission — see [SharePoint Online Requirements](/docs/accessanalyzer/1_0/requirements/connectors/sharepointonline) +- A certificate (public/private key pair) uploaded to the app registration +- Network connectivity from Access Analyzer to Microsoft Graph API (port 443) + +## Create a Service Account + +1. Navigate to **Service Accounts** in the sidebar +2. Click **Add Service Account** +3. Enter a **Name** (for example, `SharePoint Online - Graph API`) +4. Select **Certificate** as the type +5. Enter the **Client ID** (Application ID from the Azure app registration) +6. Enter the **Tenant ID** (Directory ID) +7. Upload the **Certificate** (private key `.pem` file) +8. Click **Add service account** + +## Add a SharePoint Online Source + +1. Navigate to **Configuration** > **Sources** +2. Click **Add Source** +3. Select **Data Source** as the category +4. Select **SharePoint Online** as the source type +5. Select the certificate-based service account created above +6. Click **Test Connection** to verify Graph API connectivity +7. After a successful test, click **Create Source** + +## Test Connection + +The test connection validates: + +- Certificate authentication with the Microsoft identity platform +- Graph API access with the configured permissions +- Ability to enumerate SharePoint sites diff --git a/docs/accessanalyzer/1.0/connectors/source/sharepointonline/permissionsharinglinks.md b/docs/accessanalyzer/1.0/connectors/source/sharepointonline/permissionsharinglinks.md new file mode 100644 index 0000000000..18a311c439 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/source/sharepointonline/permissionsharinglinks.md @@ -0,0 +1,35 @@ +--- +title: "Permission and Sharing Link Analysis" +description: "Analyzing SharePoint permissions and external sharing links" +sidebar_position: 30 +--- + +# Permission and Sharing Link Analysis + +The SharePoint Online connector collects permission data from SharePoint sites to identify who has access to documents and whether content is shared externally. + +## What Gets Collected + +| Data | Description | +| --- | --- | +| **Site permissions** | Users and groups with access to the site, including permission levels (Full Control, Edit, Read) | +| **Library permissions** | Custom permissions set at the document library level | +| **Item-level permissions** | Unique permissions on individual files or folders (broken inheritance) | +| **Sharing links** | Anonymous links, organization-wide links, and people-specific sharing links | + +## Sharing Link Types + +| Link Type | Description | Risk Level | +| --- | --- | --- | +| **Anyone** | Anonymous access — no authentication required | High | +| **Organization** | Anyone in the organization can access | Medium | +| **Specific people** | Only named users can access | Low | + +## How It Helps + +Permission and sharing link analysis enables you to: + +- Identify documents shared externally via anonymous links +- Find overly permissive site-level access +- Detect broken permission inheritance on sensitive documents +- Review sharing link expiration and access levels diff --git a/docs/accessanalyzer/1.0/connectors/source/sharepointonline/scanningspecificsites.md b/docs/accessanalyzer/1.0/connectors/source/sharepointonline/scanningspecificsites.md new file mode 100644 index 0000000000..e4203c5679 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/source/sharepointonline/scanningspecificsites.md @@ -0,0 +1,30 @@ +--- +title: "Scanning Specific Sites" +description: "Targeting specific SharePoint sites for scanning" +sidebar_position: 40 +--- + +# Scanning Specific Sites + +By default, the SharePoint Online connector scans all sites accessible to the configured app registration. You can narrow the scope by including or excluding specific sites. + +## Configuring Site Filters + +Site filtering is configured during scan creation in the **Configure Details** step: + +1. Navigate to **Configuration** > **Scans** +2. Create a new scan for the SharePoint Online source +3. In the **Configure Details** step, set site include or exclude filters + +## Filter Options + +| Option | Behavior | +| --- | --- | +| **Include specific sites** | Only scan the listed sites | +| **Exclude specific sites** | Scan all sites except those listed | + +## Use Cases + +- **Compliance scanning** — Scan only sites that contain regulated data (HR, Finance, Legal) +- **Incremental rollout** — Start with a subset of sites and expand over time +- **Performance** — Reduce scan duration by excluding large, low-priority sites diff --git a/docs/accessanalyzer/1.0/connectors/source/sharepointonline/sitelibraryenum.md b/docs/accessanalyzer/1.0/connectors/source/sharepointonline/sitelibraryenum.md new file mode 100644 index 0000000000..62a46f11d3 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/source/sharepointonline/sitelibraryenum.md @@ -0,0 +1,29 @@ +--- +title: "Site and Library Enumeration" +description: "Discovering SharePoint sites and document libraries" +sidebar_position: 20 +--- + +# Site and Library Enumeration + +The SharePoint Online connector discovers SharePoint sites, document libraries, and their contents through the Microsoft Graph API. + +## What Gets Discovered + +| Object Type | Description | +| --- | --- | +| **Sites** | All SharePoint Online sites accessible to the app registration | +| **Document libraries** | Libraries within each site containing files and folders | +| **Files and folders** | Individual items with metadata (name, size, modified date, author) | + +## How It Works + +1. The connector authenticates with the Graph API using the configured certificate +2. Sites are enumerated based on the app registration's permissions (`Sites.Read.All`) +3. For each site, document libraries are discovered +4. Files and folders within each library are traversed and cataloged +5. Results are sent to the Core API for storage and analysis + +## Site Filtering + +You can control which sites are scanned using include/exclude filters. See [Scanning Specific Sites](/docs/accessanalyzer/1_0/connectors/source/sharepointonline/scanningspecificsites) for details. diff --git a/docs/accessanalyzer/1.0/dashboards/_category_.json b/docs/accessanalyzer/1.0/dashboards/_category_.json new file mode 100644 index 0000000000..4795b98214 --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Dashboards and Reports", + "position": 80, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/dashboards/activedirectory.md b/docs/accessanalyzer/1.0/dashboards/activedirectory.md new file mode 100644 index 0000000000..0a72e8f46e --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards/activedirectory.md @@ -0,0 +1,8 @@ +--- +title: "Active Directory Dashboard" +description: "Active Directory identity and access insights" +sidebar_position: 20 +draft: true +--- + +# Active Directory Dashboard diff --git a/docs/accessanalyzer/1.0/dashboards/copilotreadiness.md b/docs/accessanalyzer/1.0/dashboards/copilotreadiness.md new file mode 100644 index 0000000000..ea7b3647a0 --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards/copilotreadiness.md @@ -0,0 +1,8 @@ +--- +title: "Copilot Readiness Dashboard" +description: "Microsoft 365 Copilot readiness assessment" +sidebar_position: 50 +draft: true +--- + +# Copilot Readiness Dashboard diff --git a/docs/accessanalyzer/1.0/dashboards/datasecurity.md b/docs/accessanalyzer/1.0/dashboards/datasecurity.md new file mode 100644 index 0000000000..a9db5d2e47 --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards/datasecurity.md @@ -0,0 +1,8 @@ +--- +title: "Data Security Dashboard" +description: "Data security posture and risk summary" +sidebar_position: 40 +draft: true +--- + +# Data Security Dashboard diff --git a/docs/accessanalyzer/1.0/dashboards/entraid.md b/docs/accessanalyzer/1.0/dashboards/entraid.md new file mode 100644 index 0000000000..c2f2ebf0c2 --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards/entraid.md @@ -0,0 +1,8 @@ +--- +title: "Entra ID Dashboard" +description: "Entra ID identity and access insights" +sidebar_position: 30 +draft: true +--- + +# Entra ID Dashboard diff --git a/docs/accessanalyzer/1.0/dashboards/metabase/_category_.json b/docs/accessanalyzer/1.0/dashboards/metabase/_category_.json new file mode 100644 index 0000000000..af130ea1f5 --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards/metabase/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Metabase Reports", + "position": 60, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "accessingreports" + } +} diff --git a/docs/accessanalyzer/1.0/dashboards/metabase/accessingreports.md b/docs/accessanalyzer/1.0/dashboards/metabase/accessingreports.md new file mode 100644 index 0000000000..c9919abbcc --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards/metabase/accessingreports.md @@ -0,0 +1,36 @@ +--- +title: "Accessing Embedded Reports" +description: "Using Metabase embedded reports in Access Analyzer" +sidebar_position: 10 +--- + +# Accessing Embedded Reports + +Access Analyzer embeds Metabase reports directly into the application interface. You can view, filter, and interact with reports without leaving the platform. + +## Opening a Report + +1. Navigate to the **Dashboards** section in the left navigation menu. +2. Select a dashboard from the list of available dashboards (for example, **Data Security Dashboard**). +3. The embedded Metabase report loads within the Access Analyzer interface. + +## Authentication + +Report access uses JWT-based single sign-on between the Access Analyzer Core API and Metabase. No separate Metabase credentials are required. Your Access Analyzer user permissions determine which dashboards and data you can view. + +## Interacting with Reports + +Once a report is loaded, you can: + +- **Apply filters** — Use the filter controls at the top of the dashboard to narrow results by date range, data source, compliance framework, or data type. +- **Drill down** — Click on chart elements or table rows to view detailed breakdowns of the underlying data. +- **Adjust time ranges** — Modify the reporting period to compare findings across different scan windows. + +:::note +Dashboards display data from the most recent completed scans. If you do not see expected results, verify that a [sensitive data scan](/docs/accessanalyzer/1_0/sensitivedatadiscovery/runningscan) has been run against the target data sources. +::: + +## Next Steps + +- [Save reports](/docs/accessanalyzer/1_0/dashboards/metabase/savedreports) for repeated access +- [Export report data](/docs/accessanalyzer/1_0/dashboards/metabase/exportingdata) for external use diff --git a/docs/accessanalyzer/1.0/dashboards/metabase/exportingdata.md b/docs/accessanalyzer/1.0/dashboards/metabase/exportingdata.md new file mode 100644 index 0000000000..9b8531c8e7 --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards/metabase/exportingdata.md @@ -0,0 +1,41 @@ +--- +title: "Exporting Report Data" +description: "Exporting report data for external use" +sidebar_position: 30 +--- + +# Exporting Report Data + +Access Analyzer allows you to export dashboard data from embedded Metabase reports for use in external tools, compliance documentation, or offline analysis. + +## Exporting from a Dashboard + +To export data from a dashboard or saved report: + +1. Open the desired dashboard or [saved report](/docs/accessanalyzer/1_0/dashboards/metabase/savedreports). +2. Apply any filters to scope the data to your requirements. +3. Click the **Export** button in the dashboard toolbar. +4. Select the export format: + - **CSV** — Comma-separated values for use in spreadsheets and data processing tools + - **JSON** — Structured data format for programmatic consumption + - **PDF** — Formatted report suitable for distribution and compliance documentation +5. Click **Download** to save the exported file. + +## Export Scope + +The exported data reflects the current dashboard view, including all applied filters. Only the data visible in the current report configuration is included in the export. + +| Export Format | Best For | +| --- | --- | +| CSV | Importing into Excel, Google Sheets, or data analysis tools | +| JSON | Integration with APIs, scripts, or automated reporting pipelines | +| PDF | Sharing with stakeholders, auditors, or compliance teams | + +:::warning +Exported reports may contain sensitive data findings. Handle exported files according to your organization's data handling and classification policies. +::: + +## Next Steps + +- [Configure saved reports](/docs/accessanalyzer/1_0/dashboards/metabase/savedreports) to streamline recurring exports +- [Review sensitive data scan results](/docs/accessanalyzer/1_0/sensitivedatadiscovery/reviewingresults/matchcounts) for detailed match-level data diff --git a/docs/accessanalyzer/1.0/dashboards/metabase/savedreports.md b/docs/accessanalyzer/1.0/dashboards/metabase/savedreports.md new file mode 100644 index 0000000000..8d565d14fe --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards/metabase/savedreports.md @@ -0,0 +1,38 @@ +--- +title: "Saved Reports" +description: "Creating and managing saved reports" +sidebar_position: 20 +--- + +# Saved Reports + +The saved reports feature allows you to preserve specific dashboard configurations, including applied filters and selected parameters, for quick access in future sessions. + +## Saving a Report + +1. Open a dashboard and apply the desired filters (date range, data source, compliance framework, or other parameters). +2. Click the **Save Report** button in the dashboard toolbar. +3. Enter a **Name** for the saved report. +4. Optionally add a **Description** to document the report's purpose. +5. Click **Save**. + +The saved report appears in your **Saved Reports** list for future access. + +## Managing Saved Reports + +To view and manage your saved reports: + +1. Navigate to **Dashboards** > **Saved Reports**. +2. The list displays all saved reports with their name, description, and creation date. +3. Click a saved report to load it with the preserved filter configuration. +4. To update a saved report, modify the filters and click **Save Report** again, then choose to overwrite the existing report. +5. To delete a saved report, select it and click **Delete**. + +:::note +Saved reports retain the filter configuration, not a static snapshot of the data. When you open a saved report, the dashboard applies the saved filters against the latest scan data, ensuring results are always current. +::: + +## Next Steps + +- [Export report data](/docs/accessanalyzer/1_0/dashboards/metabase/exportingdata) from a saved report configuration +- [Return to the dashboards overview](/docs/accessanalyzer/1_0/dashboards/overview) to explore other reporting options diff --git a/docs/accessanalyzer/1.0/dashboards/overview.md b/docs/accessanalyzer/1.0/dashboards/overview.md new file mode 100644 index 0000000000..d996ab6f5f --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards/overview.md @@ -0,0 +1,33 @@ +--- +title: "Dashboards and Reports" +description: "Overview of dashboards, metrics, and reporting capabilities" +sidebar_position: 10 +--- + +# Dashboards and Reports + +Netwrix Access Analyzer provides embedded analytics dashboards powered by Metabase. The **Dashboards** section gives you visual insight into your organization's data security posture, sensitive data findings, and access risk summaries. + +## Embedded Analytics + +Access Analyzer integrates Metabase as an embedded reporting engine with an airgap premium token. Authentication is handled automatically through JWT-based single sign-on from the Core API to Metabase, so users access dashboards directly from within the Access Analyzer interface without separate login credentials. + +## Available Dashboards + +Pre-built dashboards are visible in the **Dashboards** section of the application. The primary dashboard is the **Data Security Dashboard**, which provides: + +- **Sensitive data findings summary** — Aggregated match counts across all scanned sources +- **Risk summary** — High-level view of data exposure organized by severity and compliance framework +- **Trend analysis** — Changes in sensitive data findings over time + +## Reporting Capabilities + +| Feature | Description | +| --- | --- | +| [Accessing Reports](/docs/accessanalyzer/1_0/dashboards/metabase/accessingreports) | View and interact with embedded Metabase reports | +| [Saved Reports](/docs/accessanalyzer/1_0/dashboards/metabase/savedreports) | Save report configurations for repeated use | +| [Exporting Data](/docs/accessanalyzer/1_0/dashboards/metabase/exportingdata) | Export dashboard data for external analysis or compliance documentation | + +:::note +Dashboard content updates automatically as new scan results become available. Run a [sensitive data scan](/docs/accessanalyzer/1_0/sensitivedatadiscovery/runningscan) to populate dashboards with the latest findings. +::: diff --git a/docs/accessanalyzer/1.0/gettingstarted/_category_.json b/docs/accessanalyzer/1.0/gettingstarted/_category_.json new file mode 100644 index 0000000000..c8341a5bc3 --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Getting Started", + "position": 20, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/gettingstarted/dashboardwalkthrough.md b/docs/accessanalyzer/1.0/gettingstarted/dashboardwalkthrough.md new file mode 100644 index 0000000000..1416847ba0 --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/dashboardwalkthrough.md @@ -0,0 +1,44 @@ +--- +title: "Overview Dashboard Walkthrough" +description: "Navigating the main dashboard and key metrics" +sidebar_position: 30 +--- + +# Overview Dashboard Walkthrough + +After signing in, Access Analyzer displays the main interface with a sidebar navigation menu and a central content area. This page introduces the key areas of the application. + +## Sidebar Navigation + +The sidebar provides access to all major sections: + +| Section | Description | +| --- | --- | +| **Dashboards** | Pre-built Metabase dashboards for data security posture and identity analysis | +| **Reports** | Access, content, activity, and sensitive data reports | +| **Configuration** | Sources, scans, scan executions, and sensitive data settings | +| **Service Accounts** | Manage credentials used to connect to data sources | +| **Administration** | User management and system logs (administrator only) | +| **Settings** | Application-wide settings | + +## Dashboards + +The **Dashboards** section contains embedded Metabase dashboards that provide a visual summary of your environment: + +- **Data Security Dashboard** — Overview of sensitive data findings, file statistics, and framework coverage +- Additional dashboards become available as you add data sources and run scans + +Dashboards update automatically after each scan execution. + +## Configuration Section + +The **Configuration** section is where most of the day-to-day work happens: + +- **Sources** — Add and manage the data sources and identity providers Access Analyzer connects to +- **Scans** — Create, schedule, and manage access scans and sensitive data scans +- **Scan Executions** — View the history of scan runs, including status, duration, and progress +- **Sensitive Data** — Configure the detection frameworks and patterns used during sensitive data scans + +## Next Steps + +- [Your First Scan](/docs/accessanalyzer/1_0/gettingstarted/firstscan/overview) — Follow the step-by-step guide to add a source, configure a scan, and review results diff --git a/docs/accessanalyzer/1.0/gettingstarted/firstlogin.md b/docs/accessanalyzer/1.0/gettingstarted/firstlogin.md new file mode 100644 index 0000000000..defd35ef14 --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/firstlogin.md @@ -0,0 +1,52 @@ +--- +title: "First Login and Admin Setup" +description: "Initial administrator account creation and login" +sidebar_position: 20 +--- + +# First Login and Admin Setup + +After installing Access Analyzer, the first step is to access the web interface, create your administrator account, and sign in. + +## Access the Application + +Open a browser and navigate to: + +``` +https:// +``` + +Replace `` with the IP address or hostname of the VM where Access Analyzer is installed. + +:::note +Access Analyzer uses a self-signed TLS certificate by default. Your browser will display a security warning — accept the warning to proceed to the login page. To use a trusted certificate, see [SSL / TLS Configuration](/docs/accessanalyzer/1_0/install/ssl). +::: + +## Create the Administrator Account + +The first user to create an account is automatically assigned the **Administrator** role. + +1. On the login page, click **Create Account** +2. Enter the following: + - **Full Name** — Your display name + - **Email Address** — Used as your login username + - **Password** — Must meet complexity requirements + - **Confirm Password** — Re-enter the password +3. Click **Create Account** + +:::warning +The first account created receives full administrator privileges. Ensure this account is created by an authorized administrator. +::: + +## Sign In + +1. Enter the email address and password you used during account creation +2. Click **Sign In** + +You are now signed in with full administrator access. + +## Next Steps + +- [Overview Dashboard Walkthrough](/docs/accessanalyzer/1_0/gettingstarted/dashboardwalkthrough) — Explore the main interface +- [Your First Scan](/docs/accessanalyzer/1_0/gettingstarted/firstscan/overview) — Add a data source and run your first scan +- [Users and Roles](/docs/accessanalyzer/1_0/admin/users/overview) — Create additional user accounts diff --git a/docs/accessanalyzer/1.0/gettingstarted/firstscan/_category_.json b/docs/accessanalyzer/1.0/gettingstarted/firstscan/_category_.json new file mode 100644 index 0000000000..d8feb251f3 --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/firstscan/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Your First Scan", + "position": 30, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/gettingstarted/firstscan/addingsource.md b/docs/accessanalyzer/1.0/gettingstarted/firstscan/addingsource.md new file mode 100644 index 0000000000..b37b596118 --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/firstscan/addingsource.md @@ -0,0 +1,70 @@ +--- +title: "Adding a Data Source" +description: "Connect a data source using the Connect Source wizard" +sidebar_position: 20 +--- + +# Adding a Data Source + +Before scanning, you need to connect a data source to Access Analyzer. The **Connect Source** wizard guides you through a 3-step process: select the source type, configure the connection, and set up a scan. + +## Open the Connect Source Wizard + +1. Navigate to **Configuration** > **Sources** in the sidebar +2. Click **Connect Source** to open the wizard drawer + +## Step 1 — Select Source Type + +Choose the type of data source to connect: + +| Source Type | Category | Description | +| --- | --- | --- | +| **Active Directory** | IAM | Domain controllers, users, groups, and permissions | +| **Entra ID** | IAM | Azure AD tenant with users, groups, and roles | +| **File Server** | Data Source | Windows file shares (CIFS/SMB) | +| **SharePoint Online** | Data Source | SharePoint sites and document libraries | + +Select a source type card and click **Next**. + +## Step 2 — Configure the Source + +Configuration varies by source type. For this getting started guide, we'll walk through the **File Server** example — the most common first source. + +### File Server Configuration + +1. Enter a **Source Group Name** (for example, `Finance File Servers`) +2. Select or create a **Service Account**: + - Click **+ Create New Account** to add credentials inline + - Select **Username/Password** and enter the username and password for an account with read access to the target file servers + - Or select an existing service account from the dropdown +3. Optionally enter a **Domain** name (for example, `company.local`) + +### Add File Servers + +1. Click **+ Add** or the empty state area +2. Select **Add Manually** +3. Enter one or more server names or IP addresses, separated by commas or pressing **Enter** after each +4. Set the **Port** (default: `445`) +5. Click **Add file servers**, then click **Done** + +### Test Connection (Optional) + +Click **Test Connection** to verify connectivity to all servers. Each server shows its connection status (Connected, Failed, or Testing). Testing is non-blocking — you can proceed regardless of results. + +:::note +If a connection test fails, verify network connectivity on port 445 and that the service account has read access to the target shares. +::: + +Click **Next** to proceed to scan setup. + +### Other Source Types + +For detailed configuration instructions for each source type, see: + +- [Active Directory](/docs/accessanalyzer/1_0/connectors/iam/activedirectory/connectionsetup) — Domain controller configuration +- [Entra ID](/docs/accessanalyzer/1_0/connectors/iam/entraid/appregistration) — Azure AD app registration and tenant setup +- [SharePoint Online](/docs/accessanalyzer/1_0/connectors/source/sharepointonline/connectionconfig) — Site collection configuration + +## Next Step + +[Configuring a Scan](/docs/accessanalyzer/1_0/gettingstarted/firstscan/configuringscan) — Set up scanning options and schedule your first scan. diff --git a/docs/accessanalyzer/1.0/gettingstarted/firstscan/configuringscan.md b/docs/accessanalyzer/1.0/gettingstarted/firstscan/configuringscan.md new file mode 100644 index 0000000000..14df574f12 --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/firstscan/configuringscan.md @@ -0,0 +1,94 @@ +--- +title: "Configuring a Scan" +description: "Set up scanning options and schedule in the Connect Source wizard" +sidebar_position: 30 +--- + +# Configuring a Scan + +Step 3 of the Connect Source wizard configures what to scan and when. The available options depend on the source type selected in Step 1. + +## Available Scanning Options + +Select which scan types to enable for the source group. Available options vary by source type: + +### File Server Scan Types + +| Scan Type | Description | +| --- | --- | +| **Access** | Scan file server permissions and access controls | +| **Sensitive Data** | Scan file contents for sensitive data patterns (PII, credentials, PHI, financial data) | + +At least one scan type must be enabled to proceed. + +:::info +When the **Access** scan is enabled, a **Local Users and Groups** scan is also created automatically to collect local account data from each file server. This happens behind the scenes and does not require additional configuration. +::: + +### Entra ID Scan Types + +| Scan Type | Description | +| --- | --- | +| **Users, Groups and Roles** | Synchronize users, groups, and directory roles from the Azure AD tenant | + +This scan type is always enabled and cannot be disabled. Additional sync options (such as **Sync Sensitivity Labels**) may appear below the toggle. + +### Active Directory Scan Types + +| Scan Type | Description | +| --- | --- | +| **Active Directory Inventory** | Synchronize users, groups, OUs, and permissions from domain controllers | + +## Access Scan Options (File Server) + +When the **Access** scan type is enabled for a File Server source, additional configuration options appear: + +### Share Selection + +- **Include Shares** — Choose **All shares** (default) or **Custom selection** to specify specific share names +- **Exclude Shares** — Optionally list shares to skip (for example, `admin$, ipc$`) + +### Scan Depth + +- Maximum folder depth to scan (default: **50**) +- Controls how many levels of subdirectories the connector traverses + +### File-Level Permissions + +- Check **Include file-level permission data in scan results** to collect NTFS ACLs on individual files +- Disabled by default — increases scan duration on large file servers + +### Hidden Shares + +- Check **Automatically enumerate and scan hidden shares** to discover shares ending with `$` +- When enabled, an **Exclude Hidden Shares** field appears to specify hidden shares to skip (for example, `ADMIN$, C$, IPC$`) + +### Worker Threads + +- Number of concurrent workers for parallel directory enumeration (default: **3**) +- Higher values scan faster but increase load on the file server + +For detailed information about each option, see the [CIFS connector documentation](/docs/accessanalyzer/1_0/connectors/source/cifs/connectionconfig). + +## Scan Start Time + +Choose when to run the first scan: + +| Option | Description | +| --- | --- | +| **Run scan now** | Execute immediately after setup completes (default) | +| **Run scan at** | Schedule for a specific date and time — must be in the future | +| **Advanced scheduling** | Configure a recurring schedule using a cron expression | + +## Complete Setup + +Click **Complete Setup** to create the source group with all configured sources and scans. On success: + +1. The source group and all sources are created +2. Scans are created according to your configuration +3. The wizard closes and the sources list refreshes +4. Scans execute according to the selected schedule + +## Next Step + +[Running and Monitoring a Scan](/docs/accessanalyzer/1_0/gettingstarted/firstscan/runningscan) — Track scan progress and review results. diff --git a/docs/accessanalyzer/1.0/gettingstarted/firstscan/overview.md b/docs/accessanalyzer/1.0/gettingstarted/firstscan/overview.md new file mode 100644 index 0000000000..9d968a68bd --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/firstscan/overview.md @@ -0,0 +1,28 @@ +--- +title: "Your First Scan" +description: "Step-by-step guide to running your first scan" +sidebar_position: 10 +--- + +# Your First Scan + +This guide walks you through the complete workflow of adding a data source, creating a scan, running it, and reviewing the results. The example uses a CIFS/SMB file share, but the workflow is similar for all source types. + +## Workflow Summary + +| Step | Description | Page | +| --- | --- | --- | +| 1 | Create a service account with credentials for your data source | [Adding a Data Source](/docs/accessanalyzer/1_0/gettingstarted/firstscan/addingsource) | +| 2 | Add a data source and test the connection | [Adding a Data Source](/docs/accessanalyzer/1_0/gettingstarted/firstscan/addingsource) | +| 3 | Create a scan and select scan type | [Configuring a Scan](/docs/accessanalyzer/1_0/gettingstarted/firstscan/configuringscan) | +| 4 | Run the scan and monitor progress | [Running and Monitoring a Scan](/docs/accessanalyzer/1_0/gettingstarted/firstscan/runningscan) | +| 5 | Review findings in dashboards and scan results | [Viewing Results](/docs/accessanalyzer/1_0/gettingstarted/firstscan/viewingresults) | + +## Prerequisites + +Before starting, ensure you have: + +- Signed in as an administrator — see [First Login](/docs/accessanalyzer/1_0/gettingstarted/firstlogin) +- A data source available on the network (for example, a CIFS/SMB file share) +- Credentials with read access to the data source +- Network connectivity from the Access Analyzer VM to the data source (for example, port 445 for SMB) diff --git a/docs/accessanalyzer/1.0/gettingstarted/firstscan/runningscan.md b/docs/accessanalyzer/1.0/gettingstarted/firstscan/runningscan.md new file mode 100644 index 0000000000..9d9f001798 --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/firstscan/runningscan.md @@ -0,0 +1,56 @@ +--- +title: "Running and Monitoring a Scan" +description: "Execute a scan and monitor its progress" +sidebar_position: 40 +--- + +# Running and Monitoring a Scan + +Once a scan is created, you can run it immediately or let it execute on its configured schedule. + +## Running a Scan + +There are two ways to start a scan: + +- **From the scan creation wizard** — Select **Create & Run Immediately** in the final step +- **From the Scans list** — Navigate to **Configuration** > **Scans**, click the menu button on the scan row, and select **Run** + +## Monitoring Scan Progress + +Navigate to **Configuration** > **Scan Executions** to view all scan runs. + +Each execution displays: + +| Field | Description | +| --- | --- | +| **Scan Name** | The name of the scan | +| **Scan Type** | Access or Sensitive Data | +| **Source** | The data source being scanned | +| **Status** | Running, Completed, Failed, or Paused | +| **Start Time** | When the scan execution began | +| **Duration** | Elapsed time since the scan started | + +You can filter executions by scan type, source, status, date range, and duration. + +## Scan Execution Actions + +While a scan is running, the following actions are available from the execution row menu: + +| Action | Description | +| --- | --- | +| **Stop** | Cancel the running scan | +| **Pause** | Pause the scan (CIFS/SMB sources only) | +| **Resume** | Resume a paused scan (CIFS/SMB sources only) | + +## Scan Statuses + +| Status | Meaning | +| --- | --- | +| **Running** | Scan is actively processing | +| **Completed** | Scan finished successfully | +| **Failed** | Scan encountered an error — check the execution logs | +| **Paused** | Scan has been paused and can be resumed | + +## Next Step + +[Viewing Results](/docs/accessanalyzer/1_0/gettingstarted/firstscan/viewingresults) — Review the findings from your completed scan. diff --git a/docs/accessanalyzer/1.0/gettingstarted/firstscan/viewingresults.md b/docs/accessanalyzer/1.0/gettingstarted/firstscan/viewingresults.md new file mode 100644 index 0000000000..f41a7de471 --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/firstscan/viewingresults.md @@ -0,0 +1,49 @@ +--- +title: "Viewing Results" +description: "Review scan results and findings" +sidebar_position: 50 +--- + +# Viewing Results + +After a scan completes, results are available in the dashboards and reports sections. + +## Data Security Dashboard + +Navigate to **Dashboards** > **Data Security Dashboard** to view a summary of findings from your scans. The dashboard provides visualizations for: + +- Sensitive data findings by type and compliance framework +- File and data statistics +- Data exposure and risk indicators + +The dashboard updates automatically after each scan execution completes. + +## Scan Execution Details + +For per-scan results, navigate to **Configuration** > **Scan Executions**: + +1. Find the completed scan execution in the list +2. Click on the execution to view detailed results +3. Review the findings, including: + - Files and folders analyzed + - Permissions and access paths discovered + - Sensitive data matches (for sensitive data scans) + +## Reports + +Access Analyzer provides several report categories accessible from the sidebar: + +| Report Type | Description | +| --- | --- | +| **Access Reports** | Permission analysis and access path details | +| **Content Reports** | File and folder inventory statistics | +| **Sensitive Data Reports** | Sensitive data findings by category and compliance framework | + +## What's Next + +Now that you have completed your first scan and reviewed the results, consider these next steps: + +- **Add more data sources** — Connect additional file shares, SharePoint sites, or identity providers. See [Connectors](/docs/accessanalyzer/1_0/connectors/overview). +- **Configure sensitive data detection** — Customize detection patterns and taxonomy groups. See [Sensitive Data Discovery](/docs/accessanalyzer/1_0/sensitivedatadiscovery/overview). +- **Schedule recurring scans** — Set up automated scan schedules to maintain continuous visibility. See [Scans](/docs/accessanalyzer/1_0/admin/scans/overview). +- **Create additional users** — Add team members with appropriate roles. See [Users and Roles](/docs/accessanalyzer/1_0/admin/users/overview). diff --git a/docs/accessanalyzer/1.0/gettingstarted/overview.md b/docs/accessanalyzer/1.0/gettingstarted/overview.md new file mode 100644 index 0000000000..bb9c6c66f8 --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/overview.md @@ -0,0 +1,26 @@ +--- +title: "Getting Started" +description: "Get up and running with Access Analyzer" +sidebar_position: 10 +--- + +# Getting Started + +This section walks you through the initial setup steps after installing Access Analyzer, from your first login to running your first scan and reviewing results. + +## Getting Started Steps + +| Step | Description | Page | +| --- | --- | --- | +| 1 | Sign in and create your administrator account | [First Login and Admin Setup](/docs/accessanalyzer/1_0/gettingstarted/firstlogin) | +| 2 | Explore the main dashboard and navigation | [Overview Dashboard Walkthrough](/docs/accessanalyzer/1_0/gettingstarted/dashboardwalkthrough) | +| 3 | Add a data source, configure a scan, and view results | [Your First Scan](/docs/accessanalyzer/1_0/gettingstarted/firstscan/overview) | + +## Prerequisites + +Before starting this guide, ensure you have: + +- Completed the [installation](/docs/accessanalyzer/1_0/install/overview) of Access Analyzer +- Verified that all services are healthy — see [Post-Installation Validation](/docs/accessanalyzer/1_0/install/postinstall) +- Network connectivity from the Access Analyzer VM to the data sources you plan to scan +- Credentials (service account) for the data sources you want to connect diff --git a/docs/accessanalyzer/1.0/index.md b/docs/accessanalyzer/1.0/index.md new file mode 100644 index 0000000000..ee95583019 --- /dev/null +++ b/docs/accessanalyzer/1.0/index.md @@ -0,0 +1,30 @@ +--- +title: "Netwrix Access Analyzer Documentation" +description: "Netwrix Access Analyzer 1.0 product documentation - installation, administration, connectors, and sensitive data discovery" +sidebar_position: 1 +--- + +# Netwrix Access Analyzer Documentation + +Netwrix Access Analyzer is a cloud-native Data Security Posture Management (DSPM) platform that helps organizations discover, classify, and monitor sensitive data across enterprise systems and cloud storage. It provides comprehensive visibility into data access patterns, identifies compliance risks, and enables data governance at scale. + +## Key Capabilities + +- **Data Source Scanning** — Connect to CIFS/SMB file shares, SharePoint Online, and more to discover and analyze data +- **Sensitive Data Discovery** — Detect sensitive data using built-in and custom regex patterns with taxonomy-based classification +- **Identity and Access Management** — Sync users and groups from Active Directory and Entra ID to analyze permission paths +- **Activity Monitoring** — Track file access and user activity via Netwrix Activity Monitor integration +- **Dashboards and Reporting** — Visualize security posture with built-in dashboards and embedded Metabase reports + +## Documentation Sections + +- [Overview](overview/overview) — Architecture, components, and key concepts +- [Getting Started](gettingstarted/overview) — First login, dashboard walkthrough, and your first scan +- [Requirements](requirements/overview) — System, database, and connector prerequisites +- [Installation](install/overview) — Kubernetes deployment, infrastructure setup, and database initialization +- [Administration](admin/overview) — User management, sources, scans, and application settings +- [Connectors](connectors/overview) — IAM and source connector configuration +- [Sensitive Data Discovery](sensitivedatadiscovery/overview) — Patterns, taxonomy, classification, and scan results +- [Dashboards and Reports](dashboards/overview) — Built-in dashboards and Metabase reporting +- [Activity Monitoring](activitymonitoring/overview) — Syslog integration with Netwrix Activity Monitor +- [Monitoring and Troubleshooting](troubleshooting/overview) — Health checks, observability, and common issues diff --git a/docs/accessanalyzer/1.0/install/_category_.json b/docs/accessanalyzer/1.0/install/_category_.json new file mode 100644 index 0000000000..f5134e8f2b --- /dev/null +++ b/docs/accessanalyzer/1.0/install/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Installation", + "position": 40, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/install/dspmctl.md b/docs/accessanalyzer/1.0/install/dspmctl.md new file mode 100644 index 0000000000..7bdc4cc594 --- /dev/null +++ b/docs/accessanalyzer/1.0/install/dspmctl.md @@ -0,0 +1,141 @@ +--- +title: "DSPMctl CLI" +description: "Command-line reference for the DSPMctl application management tool" +sidebar_position: 45 +--- + +# DSPMctl CLI + +DSPMctl is a command-line tool installed by the Access Analyzer installer at `/usr/local/bin/dspmctl`. It provides convenient commands for managing ArgoCD-deployed applications without requiring direct `kubectl` or ArgoCD CLI interaction. + +## Commands + +### auto-status + +Display the current sync and auto-sync status of all applications: + +```bash +dspmctl auto-status +``` + +### enable-auto + +Enable auto-sync for a specific application. When auto-sync is enabled, ArgoCD automatically applies changes when the target revision is updated in the OCI registry: + +```bash +dspmctl enable-auto +``` + +**Example:** + +```bash +dspmctl enable-auto netwrix.core-api +``` + +### disable-auto + +Disable auto-sync for a specific application: + +```bash +dspmctl disable-auto +``` + +### set-revision + +Update the target revision (version) for an application or application set: + +```bash +dspmctl set-revision +``` + +**Example:** + +```bash +dspmctl set-revision netwrix 1.0.6 +``` + +### sync + +Manually trigger a sync for a specific application: + +```bash +dspmctl sync +``` + +**Example:** + +```bash +dspmctl sync netwrix.core-api +``` + +### set-helm-param + +Set one or more Helm parameter overrides for an application: + +```bash +dspmctl set-helm-param +dspmctl set-helm-param = [= ...] +``` + +**Examples:** + +```bash +# Set a single parameter +dspmctl set-helm-param netwrix.core-api image.tag v1.2.3 + +# Set multiple parameters +dspmctl set-helm-param netwrix.core-api image.tag=v1.2.3 replicaCount=2 +``` + +### version + +Display the DSPMctl version: + +```bash +dspmctl version +``` + +### help + +Display usage information: + +```bash +dspmctl --help +``` + +## Common Workflows + +### Upgrading to a New Version + +To update all applications to a new target revision: + +```bash +# Set the new version +dspmctl set-revision netwrix 1.0.7 + +# Verify applications are syncing +dspmctl auto-status + +# Force sync if needed +dspmctl sync netwrix.infra +dspmctl sync netwrix.core-api +``` + +See [Upgrading Access Analyzer](/docs/accessanalyzer/1_0/install/upgrade) for the full upgrade procedure. + +### Scaling an Application + +```bash +dspmctl set-helm-param netwrix.core-api replicaCount 3 +``` + +### Checking Deployment Health + +```bash +# Check auto-sync status +dspmctl auto-status + +# Also verify with kubectl +kubectl get apps -n argocd +kubectl get pods -n access-analyzer +``` diff --git a/docs/accessanalyzer/1.0/install/environmentvariables.md b/docs/accessanalyzer/1.0/install/environmentvariables.md new file mode 100644 index 0000000000..5b2cbb6d90 --- /dev/null +++ b/docs/accessanalyzer/1.0/install/environmentvariables.md @@ -0,0 +1,92 @@ +--- +title: "Environment Variables" +description: "CLI flags and environment variable reference for the Access Analyzer installer" +sidebar_position: 30 +--- + +# Environment Variables + +The Access Analyzer installer can be configured using command-line flags or environment variables. Environment variables are useful for scripted or automated installations. + +## CLI Flags + +``` +install.sh --license-key [options] + +Options: + --license-key Netwrix license key (required) + --target-revision Application version to deploy (default: 1.*) + --size Resource size multiplier, 1–10 (default: 1) + --accept-warnings Accept preflight warnings and continue + --dry-run Run preflight checks only, without installing + --help Display usage information +``` + +## Mandatory Variables + +| Variable | CLI Flag | Description | +| --- | --- | --- | +| `LICENSE_KEY` | `--license-key` | Netwrix license key for OCI registry authentication. Required for installation. | + +## Optional Configuration Variables + +| Variable | CLI Flag | Default | Description | +| --- | --- | --- | --- | +| `DSPM_TARGET_REVISION` | `--target-revision` | `1.*` | Target version for DSPM applications | +| `SIZE` | `--size` | `1` | Resource size multiplier (1–10). Scales memory thresholds. | +| `ACCEPT_WARNINGS` | `--accept-warnings` | `false` | Set to `true` to skip preflight warning prompts | + +## Proxy Variables + +| Variable | Description | Example | +| --- | --- | --- | +| `HTTP_PROXY` | HTTP proxy server URL | `http://proxy.example.com:8080` | +| `HTTPS_PROXY` | HTTPS proxy server URL | `http://proxy.example.com:8080` | +| `NO_PROXY` | Comma-separated list of hosts to bypass proxy | `localhost,127.0.0.1,10.0.0.0/8` | + +## Advanced Variables + +These variables are intended for specialized deployments and troubleshooting. They are not required for standard installations. + +| Variable | Default | Description | +| --- | --- | --- | +| `SKIP_AV_CHECK` | `false` | Skip antivirus detection during preflight | +| `FORCE_CA_MOUNT` | `false` | Force CA certificate bundle mounting to ArgoCD components | +| `USE_LOCAL_CHARTS` | `false` | Use local Helm charts instead of OCI registry | +| `USE_MIRRORED_IMAGES` | `true` | Use mirrored container images | +| `DISABLE_DEX` | `true` | Disable the Dex identity provider in ArgoCD | +| `DISABLE_NOTIFICATIONS` | `true` | Disable ArgoCD notifications | +| `DSPM_INSTALL_DEBUG` | Not set | Enable debug logging for the installer | + +## Examples + +**Basic installation:** + +```bash +export LICENSE_KEY='' +curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash - +``` + +**Installation with a specific version:** + +```bash +export LICENSE_KEY='' +curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- --target-revision "1.0.6" +``` + +**Scaled deployment (2x resources):** + +```bash +export LICENSE_KEY='' +curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- --size 2 +``` + +**Installation behind a proxy:** + +```bash +export LICENSE_KEY='' +export HTTP_PROXY="http://proxy.example.com:8080" +export HTTPS_PROXY="http://proxy.example.com:8080" +export NO_PROXY="localhost,127.0.0.1" +curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash - +``` diff --git a/docs/accessanalyzer/1.0/install/network.md b/docs/accessanalyzer/1.0/install/network.md new file mode 100644 index 0000000000..8e188d3da6 --- /dev/null +++ b/docs/accessanalyzer/1.0/install/network.md @@ -0,0 +1,96 @@ +--- +title: "Network Configuration" +description: "Network requirements, outbound endpoints, and firewall rules for Access Analyzer" +sidebar_position: 20 +--- + +# Network Configuration + +Access Analyzer requires outbound HTTPS connectivity during installation to download Kubernetes components, container images, and application packages. This page lists the required endpoints and provides firewall configuration examples. + +## Required Outbound Endpoints + +The following endpoints must be reachable over HTTPS (port 443) from the Access Analyzer VM: + +| Endpoint | Purpose | +| --- | --- | +| `get.k3s.io` | K3s installer download | +| `raw.githubusercontent.com` | ArgoCD manifests (bootstrap only) | +| `oci.pkg.keygen.sh` | Netwrix OCI registry — Helm charts and application images | +| `docker.io` / `docker.com` | Container base images (PostgreSQL, ClickHouse, Redis) | + +:::note +All application packages are distributed through the Netwrix OCI registry at `oci.pkg.keygen.sh`. Access is authenticated with your license key. No external Git repository access is required. +::: + +## Firewall Rules + +### Azure VMs (Network Security Group) + +```bash +az network nsg rule create \ + --resource-group \ + --nsg-name \ + --name AllowHTTPSOutbound \ + --protocol Tcp \ + --priority 1010 \ + --destination-port-range 443 \ + --direction Outbound \ + --access Allow +``` + +### AWS EC2 (Security Groups) + +```bash +aws ec2 authorize-security-group-egress \ + --group-id \ + --protocol tcp \ + --port 443 \ + --cidr 0.0.0.0/0 +``` + +### On-Premises / Bare Metal + +Using `ufw` (Ubuntu Firewall): + +```bash +sudo ufw allow out 443/tcp +``` + +Using `iptables`: + +```bash +sudo iptables -A OUTPUT -p tcp --dport 443 -j ACCEPT +``` + +## Proxy Configuration + +If your environment routes outbound traffic through a proxy server, set the following environment variables before running the installer: + +```bash +export HTTP_PROXY="http://:" +export HTTPS_PROXY="http://:" +export NO_PROXY="localhost,127.0.0.1,10.0.0.0/8" +``` + +See [Environment Variables](/docs/accessanalyzer/1_0/install/environmentvariables) for the full list of proxy-related variables. + +## Verifying Connectivity + +Test outbound access to the required endpoints before installation: + +```bash +# Test K3s installer access +curl -I https://get.k3s.io + +# Test Netwrix registry access +curl -I https://oci.pkg.keygen.sh:443 +``` + +## Common Network Issues + +| Issue | Symptom | Solution | +| --- | --- | --- | +| Applications not syncing | `connection refused` to Keygen | Verify outbound HTTPS (443) to `oci.pkg.keygen.sh` | +| K3s installation fails | Download errors | Check connectivity to `get.k3s.io` | +| Container image pull failures | `ImagePullBackOff` pod status | Verify access to `oci.pkg.keygen.sh` and license key validity | diff --git a/docs/accessanalyzer/1.0/install/overview.md b/docs/accessanalyzer/1.0/install/overview.md new file mode 100644 index 0000000000..af5712a7a3 --- /dev/null +++ b/docs/accessanalyzer/1.0/install/overview.md @@ -0,0 +1,49 @@ +--- +title: "Installation" +description: "Installation and deployment overview for Netwrix Access Analyzer" +sidebar_position: 1 +--- + +# Installation + +Netwrix Access Analyzer is deployed as a self-contained Kubernetes cluster on a single Linux virtual machine. The automated installer provisions all required infrastructure components — including K3s, ArgoCD, databases, and application services — with a single command. + +## Installation Paths + +Choose the installation path that best fits your needs: + +| Path | Description | Audience | +| --- | --- | --- | +| [Quick Install](/docs/accessanalyzer/1_0/install/quickinstall) | Single-page guide to get Access Analyzer running fast | Experienced Linux admins | +| [Step-by-Step Install](/docs/accessanalyzer/1_0/install/stepbystep) | Detailed walkthrough with explanations for each phase | First-time installers | + +## Before You Begin + +Review the following requirements before starting installation: + +- [Hardware and System Requirements](/docs/accessanalyzer/1_0/install/requirements) — CPU, memory, disk, OS, and virtualization +- [Network Configuration](/docs/accessanalyzer/1_0/install/network) — Outbound endpoints and firewall rules +- [Preflight Checks](/docs/accessanalyzer/1_0/install/preflight) — Automated system validation and dry-run mode + +## What the Installer Does + +The installer automates the entire deployment in approximately 15–30 minutes: + +1. **Validates prerequisites** — Runs preflight checks for hardware, OS, and network +2. **Deploys K3s** — Installs a lightweight Kubernetes distribution (v1.33.4) with secrets-at-rest encryption +3. **Installs ArgoCD** — Sets up GitOps-based application lifecycle management (v3.2.0) +4. **Deploys applications** — Pulls Helm charts from the Netwrix OCI registry and deploys all services +5. **Verifies health** — Monitors application health until all components are operational + +## After Installation + +- [Post-Installation Validation](/docs/accessanalyzer/1_0/install/postinstall) — Verify cluster health and access the ArgoCD UI +- [SSL / TLS Configuration](/docs/accessanalyzer/1_0/install/ssl) — Certificate auto-detection and custom CA bundles +- [DSPMctl CLI](/docs/accessanalyzer/1_0/install/dspmctl) — Manage applications with the built-in command-line tool + +## Additional Topics + +- [Environment Variables](/docs/accessanalyzer/1_0/install/environmentvariables) — CLI flags and environment variable reference +- [Upgrading Access Analyzer](/docs/accessanalyzer/1_0/install/upgrade) — Update to a new version +- [Uninstalling Access Analyzer](/docs/accessanalyzer/1_0/install/uninstall) — Remove the installation +- [Security Best Practices](/docs/accessanalyzer/1_0/install/security) — Harden your deployment diff --git a/docs/accessanalyzer/1.0/install/postinstall.md b/docs/accessanalyzer/1.0/install/postinstall.md new file mode 100644 index 0000000000..5f9372022a --- /dev/null +++ b/docs/accessanalyzer/1.0/install/postinstall.md @@ -0,0 +1,97 @@ +--- +title: "Post-Installation Validation" +description: "Verify cluster health and application status after installation" +sidebar_position: 40 +--- + +# Post-Installation Validation + +After the installer completes, validate that all Access Analyzer components are running correctly. + +## Cluster Health + +Verify that all Kubernetes pods are healthy: + +```bash +kubectl get pods -A -o wide +``` + +All pods should be in one of these states: + +| Status | Meaning | +| --- | --- | +| `Running` | Pod is active and healthy | +| `Completed` | One-time job completed successfully | + +If any pods show `CrashLoopBackOff`, `Error`, or `ImagePullBackOff`, see [Troubleshooting](/docs/accessanalyzer/1_0/troubleshooting/overview). + +## ArgoCD Application Status + +Check the sync and health status of all ArgoCD-managed applications: + +```bash +kubectl get apps -n argocd +``` + +Each application should show: + +| Field | Expected Value | +| --- | --- | +| **SYNC STATUS** | `Synced` | +| **HEALTH STATUS** | `Healthy` | + +## ArgoCD UI + +Access the ArgoCD web interface for a visual overview of all applications: + +1. Start port forwarding: + + ```bash + kubectl port-forward svc/argocd-server -n argocd 8090:443 + ``` + +2. Open `https://localhost:8090` in a browser + +3. Retrieve the admin password: + + ```bash + kubectl -n argocd get secret argocd-initial-admin-secret \ + -o jsonpath='{.data.password}' | base64 -d; echo + ``` + +4. Sign in with username `admin` and the retrieved password + +The ArgoCD dashboard displays each application's sync status, health, and resource tree. + +## Application Health Table + +The following components should be deployed and healthy after a successful installation: + +| Component | Namespace | Type | +| --- | --- | --- | +| **Core API** | `access-analyzer` | Rails application server | +| **Web Application** | `access-analyzer` | React frontend | +| **Connector API** | `access-analyzer` | Go connector execution service | +| **PostgreSQL** | `access-analyzer` | Primary relational database | +| **ClickHouse** | `access-analyzer` | Analytics and log storage | +| **Redis** | `access-analyzer` | Session cache and job queues | +| **Metabase** | `access-analyzer` | Embedded analytics dashboards | +| **Traefik** | `kube-system` | Ingress controller and routing | +| **OpenTelemetry Collector** | `access-analyzer` | Observability data pipeline | +| **Prometheus** | `access-analyzer` | Metrics collection | +| **ArgoCD** | `argocd` | GitOps application controller | + +## Resource Usage + +Monitor node-level resource consumption: + +```bash +kubectl top nodes +kubectl top pods -A --sort-by=memory +``` + +## Next Steps + +- [Create your first admin account](/docs/accessanalyzer/1_0/gettingstarted/firstlogin) and sign in +- [Configure a data source](/docs/accessanalyzer/1_0/gettingstarted/firstscan/overview) and run your first scan +- Review [DSPMctl CLI](/docs/accessanalyzer/1_0/install/dspmctl) for ongoing application management diff --git a/docs/accessanalyzer/1.0/install/preflight.md b/docs/accessanalyzer/1.0/install/preflight.md new file mode 100644 index 0000000000..6ac77af940 --- /dev/null +++ b/docs/accessanalyzer/1.0/install/preflight.md @@ -0,0 +1,111 @@ +--- +title: "Preflight Checks" +description: "System validation checks performed before installation" +sidebar_position: 25 +--- + +# Preflight Checks + +The Access Analyzer installer performs comprehensive system validation before any installation steps begin. Preflight checks verify hardware resources, kernel capabilities, and system access to prevent partial installation failures. + +## Dry-Run Mode + +Run preflight checks without installing anything using the `--dry-run` flag: + +```bash +export LICENSE_KEY='' +curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- --dry-run +``` + +Dry-run mode performs all validation checks and writes results to `/var/log/dspm-preflight.json`, then exits without modifying the system. + +## Phase 1: System Resource Validation + +| Check | Minimum | Recommended | Failure Behavior | +| --- | --- | --- | --- | +| **Total memory** | 8 GB | 16 GB | FAIL — installation blocked | +| **Available memory** | 4 GB (during install) | — | FAIL — installation blocked | +| **CPU cores** | 2 vCPUs | 4 vCPUs | FAIL — installation blocked | +| **Disk space (`/`, `/var`, `/var/lib`)** | 20 GB free | 50 GB free | FAIL — installation blocked | +| **Disk space (`/var/log`)** | 5 GB free | — | FAIL — installation blocked | +| **Disk space (`/etc`)** | 1 GB free | — | FAIL — installation blocked | +| **Write access** | `/var`, `/tmp`, `/etc` | — | FAIL — installation blocked | +| **Swap** | None required | 2–4 GB if RAM < 16 GB | WARN — continues with warning | +| **Dynamic memory** | N/A | Static allocation | WARN — continues with warning | + +## Phase 2: Kernel and System Access + +| Check | Requirement | Failure Behavior | +| --- | --- | --- | +| **System directories** | Write access to `/var` and `/etc` | FAIL — installation blocked | +| **Kernel modules** | `/proc/modules` readable | FAIL — installation blocked | +| **Control groups** | cgroups v1 or v2 with memory and CPU controllers | FAIL — installation blocked | +| **Overlay filesystem** | `overlay` kernel module loaded or available | FAIL — installation blocked | +| **Linux namespaces** | NET, PID, IPC, UTS, MNT, USER | FAIL — installation blocked | + +## Antivirus Detection + +The installer scans for active antivirus agents that may interfere with Kubernetes container operations: + +- Microsoft Defender for Endpoint (mdatp) +- CrowdStrike Falcon +- ClamAV +- Sophos +- Carbon Black +- Trend Micro + +If an antivirus agent is detected, the installer issues a warning. To skip this check, set the `SKIP_AV_CHECK` environment variable: + +```bash +export SKIP_AV_CHECK=true +``` + +## Preflight Result Log + +All preflight results are written to `/var/log/dspm-preflight.json` in structured JSON format: + +```json +{ + "timestamp": "2026-01-15T10:30:00Z", + "overall_status": "PASS", + "thresholds": { + "min_ram_gb": 8, + "min_cpu_cores": 2, + "min_disk_gb": 20 + }, + "checks": [ + { + "status": "PASS", + "component": "Memory", + "message": "Total memory sufficient for DSPM installation", + "current_value": "15.56 GB", + "threshold": "8 GB minimum" + } + ] +} +``` + +## Handling Warnings + +When preflight checks produce warnings (but no failures), the installer prompts for confirmation before proceeding. To automatically accept warnings — for example, in automated or scripted deployments — use one of the following: + +```bash +# CLI flag +curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- --accept-warnings + +# Environment variable +export ACCEPT_WARNINGS=true +``` + +## Exit Codes + +The installer uses specific exit codes to indicate failure categories: + +| Exit Code | Meaning | +| --- | --- | +| `0` | Success | +| `10` | License validation error | +| `50` | K3s installation error | +| `60` | ArgoCD installation error | +| `70` | Application deployment timeout | +| `80` | Preflight check failure | diff --git a/docs/accessanalyzer/1.0/install/quickinstall.md b/docs/accessanalyzer/1.0/install/quickinstall.md new file mode 100644 index 0000000000..f3e9e35808 --- /dev/null +++ b/docs/accessanalyzer/1.0/install/quickinstall.md @@ -0,0 +1,128 @@ +--- +title: "Quick Install" +description: "Get Access Analyzer up and running in minutes with this streamlined installation guide" +sidebar_position: 5 +--- + +# Quick Install + +This guide walks you through installing Netwrix Access Analyzer on a fresh Linux VM. For detailed explanations of each step, see the [Step-by-Step Installation](/docs/accessanalyzer/1_0/install/stepbystep) guide. + +## Prerequisites Checklist + +Before running the installer, confirm the following: + +| Requirement | Minimum | Recommended | +| --- | --- | --- | +| **Operating System** | Ubuntu 24.04 LTS (x86_64) | — | +| **Memory** | 8 GB RAM | 16 GB RAM | +| **CPU** | 2 vCPUs | 4 vCPUs | +| **Disk Space** | 20 GB free | 50 GB free | +| **Network** | Outbound HTTPS (port 443) | — | +| **License** | Valid Netwrix license key | — | + +:::note +If running on a hypervisor, configure **static memory allocation** (not dynamic/ballooned memory). See [Hardware and System Requirements](/docs/accessanalyzer/1_0/install/requirements) for hypervisor-specific instructions. +::: + +## Step 1: Prepare the System + +Update the operating system and verify internet connectivity: + +```bash +sudo apt update && sudo apt upgrade -y + +# Verify outbound access to the Netwrix registry +curl -I https://oci.pkg.keygen.sh:443 +``` + +## Step 2: Set Your License Key + +```bash +export LICENSE_KEY='' +``` + +:::warning +Your license key grants access to the Netwrix package registry. Keep it confidential and clear your shell history after installation. See [Security Best Practices](/docs/accessanalyzer/1_0/install/security). +::: + +## Step 3: Run the Installer + +Download and execute the installer in a single command: + +```bash +curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash - +``` + +The installer performs the following automatically: + +1. Preflight system validation (memory, CPU, disk, kernel) +2. K3s Kubernetes deployment (v1.33.4) +3. ArgoCD installation (v3.2.0) +4. Application deployment from the Netwrix OCI registry +5. Health verification of all components + +:::note +Installation typically takes 15–30 minutes depending on network speed and system resources. The installer displays progress in real time. +::: + +## Step 4: Verify the Installation + +After the installer completes, confirm all pods are running: + +```bash +kubectl get pods -A +``` + +All pods should show a `Running` or `Completed` status. Check ArgoCD application sync status: + +```bash +kubectl get apps -n argocd +``` + +## Step 5: Access the Application + +Open a browser and navigate to: + +``` +https:// +``` + +:::note +Access Analyzer uses a self-signed TLS certificate by default. Accept the browser security warning to proceed. +::: + +## Step 6: Create Your Admin Account + +1. On the login page, click **Create Account** +2. Enter your name, email address, and password +3. Click **Create Account** to finalize + +The first account created automatically receives the **Administrator** role. + +## Step 7: Sign In + +1. Enter your email address and password +2. Click **Sign In** + +You are now signed in to Netwrix Access Analyzer. See [Getting Started](/docs/accessanalyzer/1_0/gettingstarted/overview) for next steps, including configuring your first data source and running a scan. + +## Optional: Validate with Dry Run + +To validate system readiness without installing, use dry-run mode: + +```bash +curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- --dry-run +``` + +This runs all [preflight checks](/docs/accessanalyzer/1_0/install/preflight) and writes results to `/var/log/dspm-preflight.json` without modifying the system. + +## Troubleshooting + +If the installation fails, check the installer log: + +```bash +cat /var/log/dspm-installer.log +``` + +For common issues and resolutions, see [Troubleshooting](/docs/accessanalyzer/1_0/troubleshooting/overview). diff --git a/docs/accessanalyzer/1.0/install/requirements.md b/docs/accessanalyzer/1.0/install/requirements.md new file mode 100644 index 0000000000..885dc0fdaf --- /dev/null +++ b/docs/accessanalyzer/1.0/install/requirements.md @@ -0,0 +1,104 @@ +--- +title: "Hardware and System Requirements" +description: "System requirements for deploying Access Analyzer including hardware, OS, and virtualization" +sidebar_position: 10 +--- + +# Hardware and System Requirements + +Access Analyzer is deployed on a single Linux virtual machine. The installer runs preflight checks to validate that your system meets these requirements before installation begins. + +## Deployment Sizing + +| Size | CPU | Memory | Disk | Use Case | +| --- | --- | --- | --- | --- | +| **Small** | 2 vCPUs (4 recommended) | 8 GB (16 GB recommended) | 20 GB free (50 GB recommended) | Evaluation and small environments | +| **Medium** | 8 vCPUs | 32 GB | 100 GB SSD | Mid-size environments | +| **Large** | 16 vCPUs | 64 GB | 500 GB SSD | Large enterprise environments | + +:::note +The `--size` flag scales memory requirements by the specified multiplier. For example, `--size 2` doubles the minimum and recommended memory thresholds. See [Environment Variables](/docs/accessanalyzer/1_0/install/environmentvariables) for details. +::: + +## Disk Space Requirements + +The installer validates free space on the following paths: + +| Path | Minimum Free Space | Purpose | +| --- | --- | --- | +| `/` | 20 GB | Root filesystem | +| `/var` | 20 GB | K3s data, containers, logs | +| `/var/lib` | 20 GB | K3s data directory | +| `/var/log` | 5 GB | System and application logs | +| `/etc` | 1 GB | Configuration files | + +Write access is also verified for `/var`, `/tmp`, and `/etc`. + +## Operating System + +| Requirement | Value | +| --- | --- | +| **Distribution** | Ubuntu 24.04 LTS | +| **Architecture** | x86_64 (amd64) | +| **Kernel** | 5.15 or later | + +## Kernel and Container Runtime Requirements + +The installer validates the following kernel features required for Kubernetes container operation: + +| Feature | Description | +| --- | --- | +| **Linux Namespaces** | NET, PID, IPC, UTS, MNT, USER — required for container isolation | +| **Control Groups (cgroups)** | v1 or v2 with memory and CPU controllers | +| **Overlay Filesystem** | Kernel module for container image layers | +| **iptables** | Required for Kubernetes networking | + +## Virtualization and Hypervisor Configuration + +When deploying on a virtual machine, configure **static memory allocation** to ensure consistent performance. Dynamic or ballooned memory can cause the installer to underestimate available resources and lead to out-of-memory conditions during operation. + +### VMware vSphere / ESXi + +Disable memory ballooning in vSphere client under **VM Settings** > **VM Options** > **Advanced** > **Edit Configuration**: + +``` +sched.mem.pshare.enable = "FALSE" +mem.balloon.enable = "FALSE" +``` + +### Microsoft Hyper-V + +Configure static memory instead of dynamic memory: + +```powershell +Set-VMMemory -VMName "" -DynamicMemoryEnabled $false -StartupBytes 16GB +``` + +### KVM / QEMU + +Use hugepages for better memory performance. Add the following to your VM XML configuration: + +```xml + + + +``` + +## Swap Configuration + +| System Memory | Swap Recommendation | +| --- | --- | +| 16 GB or more | Optional | +| Less than 16 GB | 2–4 GB recommended | + +If no swap is configured on a system with less than 16 GB of RAM, the installer issues a warning. To create a swap file: + +```bash +sudo fallocate -l 4G /swapfile +sudo chmod 600 /swapfile +sudo mkswap /swapfile +sudo swapon /swapfile + +# Make permanent +echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab +``` diff --git a/docs/accessanalyzer/1.0/install/security.md b/docs/accessanalyzer/1.0/install/security.md new file mode 100644 index 0000000000..31ce8a735d --- /dev/null +++ b/docs/accessanalyzer/1.0/install/security.md @@ -0,0 +1,65 @@ +--- +title: "Security Best Practices" +description: "Security hardening recommendations for Access Analyzer deployments" +sidebar_position: 90 +--- + +# Security Best Practices + +Follow these recommendations to harden your Access Analyzer deployment. + +## License Key Protection + +Your Netwrix license key provides access to the OCI package registry. Treat it as a credential: + +- Do not commit license keys to version control +- Do not store license keys in plaintext configuration files +- Clear shell history after setting the `LICENSE_KEY` environment variable: + + ```bash + history -c + ``` + +## Network Security + +- Restrict access to the K3s API server (port 6443) to trusted networks only +- Limit inbound access to the Access Analyzer web interface to authorized IP ranges +- Use firewall rules to allow only the minimum required outbound endpoints — see [Network Configuration](/docs/accessanalyzer/1_0/install/network) + +## TLS / SSL + +- Replace the default self-signed certificate with a certificate issued by a trusted CA for production use +- Ensure outbound TLS verification is enabled by mounting your organization's CA bundle — see [SSL / TLS Configuration](/docs/accessanalyzer/1_0/install/ssl) + +## RBAC and Access Control + +- Limit the number of administrator accounts +- Use the **Viewer** role for users who only need read access +- Review user accounts periodically and remove unused accounts + +## Token and Credential Rotation + +- Rotate the ArgoCD admin password after initial setup: + + ```bash + kubectl -n argocd patch secret argocd-initial-admin-secret \ + -p '{"data": {"password": "'$(echo -n '' | base64)'"}}' + ``` + +- Rotate service account credentials on a regular schedule + +## Audit Logging + +- Access Analyzer maintains an audit log of user actions — review it regularly in **Settings** > **Audit Logs** +- Monitor the installer log at `/var/log/dspm-installer.log` for installation-related events +- Monitor ArgoCD logs for application sync events: + + ```bash + kubectl logs -n argocd deployment/argocd-server + ``` + +## Kubernetes Security + +- Secrets at rest are encrypted by default (K3s `--secrets-encryption` flag) +- Kubeconfig file permissions are set to `644` — restrict further if the VM is shared +- Regularly apply OS security patches to the host VM diff --git a/docs/accessanalyzer/1.0/install/ssl.md b/docs/accessanalyzer/1.0/install/ssl.md new file mode 100644 index 0000000000..cebd210517 --- /dev/null +++ b/docs/accessanalyzer/1.0/install/ssl.md @@ -0,0 +1,56 @@ +--- +title: "SSL / TLS Configuration" +description: "Certificate auto-detection and custom CA bundle configuration for Access Analyzer" +sidebar_position: 60 +--- + +# SSL / TLS Configuration + +Access Analyzer uses HTTPS for all client-facing traffic, served through Traefik as the ingress controller. By default, a self-signed TLS certificate is generated during installation. This page covers certificate handling and custom CA bundle configuration. + +## Default Behavior + +After installation, Access Analyzer is accessible at `https://`. The default self-signed certificate causes browsers to display a security warning on first access. + +## Certificate Auto-Detection + +During installation, the installer scans for existing CA certificate bundles on the system. If a bundle is found, it is automatically mounted into ArgoCD components to enable TLS verification for outbound connections to the OCI registry and other external services. + +The installer searches the following paths: + +| Path | Description | +| --- | --- | +| `/etc/ssl/certs/ca-certificates.crt` | Debian/Ubuntu CA bundle | +| `/etc/pki/tls/certs/ca-bundle.crt` | RHEL/CentOS CA bundle | +| `/etc/ssl/ca-bundle.pem` | SUSE CA bundle | +| `/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem` | RHEL trust store | +| `/etc/ssl/cert.pem` | Alpine/macOS CA bundle | +| `/usr/local/share/ca-certificates/` | Custom CA directory | + +## Forcing CA Bundle Mounting + +If the installer does not detect your CA bundle automatically, or if you are using a custom internal CA, force CA bundle mounting with the `FORCE_CA_MOUNT` environment variable: + +```bash +export FORCE_CA_MOUNT=true +export LICENSE_KEY='' +curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash - +``` + +## Adding Custom CA Certificates + +To add a custom CA certificate to the system trust store before installation: + +```bash +# Copy your CA certificate to the system trust directory +sudo cp your-ca-cert.crt /usr/local/share/ca-certificates/ + +# Update the system CA bundle +sudo update-ca-certificates +``` + +Run the installer after updating the trust store. The installer will automatically detect and mount the updated bundle. + +## TLS for Internal Services + +All internal service-to-service communication within the Kubernetes cluster uses the cluster's internal networking. Traefik handles TLS termination at the ingress layer and routes traffic to backend services. diff --git a/docs/accessanalyzer/1.0/install/stepbystep.md b/docs/accessanalyzer/1.0/install/stepbystep.md new file mode 100644 index 0000000000..bd418170a7 --- /dev/null +++ b/docs/accessanalyzer/1.0/install/stepbystep.md @@ -0,0 +1,150 @@ +--- +title: "Step-by-Step Installation" +description: "Detailed walkthrough of the Access Analyzer installation process" +sidebar_position: 35 +--- + +# Step-by-Step Installation + +This guide provides a detailed walkthrough of the Netwrix Access Analyzer installation process with explanations for each phase. For a condensed version, see the [Quick Install](/docs/accessanalyzer/1_0/install/quickinstall) guide. + +## Pre-Installation Checklist + +Complete the following before starting the installer: + +| Step | Action | Reference | +| --- | --- | --- | +| 1 | Provision a Linux VM meeting hardware requirements | [Hardware and System Requirements](/docs/accessanalyzer/1_0/install/requirements) | +| 2 | Configure static memory allocation on the hypervisor | [Virtualization Configuration](/docs/accessanalyzer/1_0/install/requirements#virtualization-and-hypervisor-configuration) | +| 3 | Verify outbound HTTPS connectivity to required endpoints | [Network Configuration](/docs/accessanalyzer/1_0/install/network) | +| 4 | Obtain your Netwrix license key | Contact Netwrix Sales or Support | +| 5 | Update the operating system | See step 1 below | + +## Step 1: Update the Operating System + +Ensure all system packages are current: + +```bash +sudo apt update && sudo apt upgrade -y +``` + +Reboot if kernel updates were applied: + +```bash +sudo reboot +``` + +## Step 2: Validate System Readiness (Optional) + +Run the installer in dry-run mode to verify that the system meets all requirements without making changes: + +```bash +export LICENSE_KEY='' +curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- --dry-run +``` + +Review the results in `/var/log/dspm-preflight.json`. Address any `FAIL` items before proceeding. See [Preflight Checks](/docs/accessanalyzer/1_0/install/preflight) for details on each check. + +## Step 3: Set the License Key + +Export your Netwrix license key as an environment variable: + +```bash +export LICENSE_KEY='' +``` + +:::warning +Do not store the license key in scripts or configuration files that are committed to version control. Clear your shell history after installation — see [Security Best Practices](/docs/accessanalyzer/1_0/install/security). +::: + +## Step 4: Run the Installer + +Download and execute the installer: + +```bash +curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash - +``` + +The installer executes the following phases automatically: + +### Phase 1 — Preflight Checks + +The installer validates system resources (memory, CPU, disk), kernel features (cgroups, overlay FS, namespaces), and system access. If any critical check fails, the installer exits with code `80`. If warnings are present, you are prompted to continue or abort. + +### Phase 2 — K3s Installation + +K3s (v1.33.4+k3s1) is deployed as a lightweight Kubernetes distribution. The installer configures: + +- Kubeconfig permissions (`644`) +- Secrets-at-rest encryption +- K3s service name `dspm` + +### Phase 3 — ArgoCD Installation + +ArgoCD (v3.2.0) is deployed using Kustomize-based manifests with dynamic patches. ArgoCD provides GitOps-based application lifecycle management for all Access Analyzer components. + +### Phase 4 — DSPMctl Wrapper + +The `dspmctl` command-line tool is installed to `/usr/local/bin/dspmctl`. This tool provides convenient commands for managing ArgoCD applications. See [DSPMctl CLI](/docs/accessanalyzer/1_0/install/dspmctl). + +### Phase 5 — Application Deployment + +Applications are deployed from the Netwrix OCI registry (`oci://oci.pkg.keygen.sh/netwrix/dspm-apps-helm`). ArgoCD pulls Helm charts and deploys all services into the `access-analyzer` namespace. + +### Phase 6 — Health Verification + +The installer monitors application health with a 30-minute timeout, checking every 2 seconds. Once all applications report healthy status, the installer prints a success summary. + +## Step 5: Verify the Installation + +After the installer completes successfully, verify the cluster state: + +```bash +# Check all pods across all namespaces +kubectl get pods -A + +# Check ArgoCD application sync status +kubectl get apps -n argocd + +# Check node resource usage +kubectl top nodes +``` + +All pods should be in `Running` or `Completed` status. All ArgoCD applications should show `Synced` and `Healthy`. + +## Step 6: Access the Application + +Open a browser and navigate to: + +``` +https:// +``` + +:::note +Access Analyzer uses a self-signed TLS certificate by default. Your browser will display a security warning — accept it to proceed. See [SSL / TLS Configuration](/docs/accessanalyzer/1_0/install/ssl) for custom certificate setup. +::: + +## Step 7: Create the First Admin Account + +1. On the login page, click **Create Account** +2. Enter your full name, email address, and a password +3. Click **Create Account** + +The first account created is automatically assigned the **Administrator** role with full access to all features. + +## Step 8: Sign In + +1. Enter your email address and password +2. Click **Sign In** + +You are now ready to begin configuring Access Analyzer. See [Getting Started](/docs/accessanalyzer/1_0/gettingstarted/overview) for your next steps. + +## Installation Log + +The installer writes a detailed log to `/var/log/dspm-installer.log`. If the installation fails, review this file for diagnostic information: + +```bash +cat /var/log/dspm-installer.log +``` + +For additional troubleshooting guidance, see [Troubleshooting](/docs/accessanalyzer/1_0/troubleshooting/overview). diff --git a/docs/accessanalyzer/1.0/install/uninstall.md b/docs/accessanalyzer/1.0/install/uninstall.md new file mode 100644 index 0000000000..87d09af82f --- /dev/null +++ b/docs/accessanalyzer/1.0/install/uninstall.md @@ -0,0 +1,52 @@ +--- +title: "Uninstalling Access Analyzer" +description: "Remove Access Analyzer and all associated components" +sidebar_position: 80 +--- + +# Uninstalling Access Analyzer + +To completely remove Access Analyzer from the system, run the K3s uninstall script provided by the installer. + +:::warning +Uninstalling removes all Kubernetes resources, databases, and application data. This action is irreversible. Back up any data you need before proceeding. +::: + +## Uninstall Procedure + +### Step 1: Run the Uninstall Script + +```bash +sudo /usr/local/bin/k3s-dspm-uninstall.sh +``` + +This script: + +- Stops and removes the K3s service +- Deletes all Kubernetes resources (pods, services, volumes) +- Removes K3s binaries and configuration +- Cleans up container images and data + +### Step 2: Remove Remaining Configuration + +Remove the kubeconfig and DSPMctl configuration: + +```bash +rm -rf ~/.kube/config +sudo rm -rf /opt/dspm +sudo rm -f /usr/local/bin/dspmctl +``` + +### Step 3: Verify Removal + +Confirm that K3s is no longer running: + +```bash +systemctl status k3s-dspm +``` + +The service should not be found or should show as inactive. + +## Reinstallation + +After uninstalling, you can reinstall Access Analyzer by running the installer again. See [Quick Install](/docs/accessanalyzer/1_0/install/quickinstall) or [Step-by-Step Installation](/docs/accessanalyzer/1_0/install/stepbystep). diff --git a/docs/accessanalyzer/1.0/install/upgrade.md b/docs/accessanalyzer/1.0/install/upgrade.md new file mode 100644 index 0000000000..868b81dc33 --- /dev/null +++ b/docs/accessanalyzer/1.0/install/upgrade.md @@ -0,0 +1,77 @@ +--- +title: "Upgrading Access Analyzer" +description: "Update Access Analyzer to a new version using DSPMctl" +sidebar_position: 70 +--- + +# Upgrading Access Analyzer + +Access Analyzer uses ArgoCD for GitOps-based application management. Upgrades are performed by updating the target revision, which triggers ArgoCD to pull and deploy the new version from the Netwrix OCI registry. + +## Upgrade Procedure + +### Step 1: Check Current Version + +```bash +dspmctl auto-status +``` + +Note the current target revision displayed for each application. + +### Step 2: Set the New Target Revision + +Update the target revision to the desired version: + +```bash +dspmctl set-revision netwrix +``` + +**Example:** + +```bash +dspmctl set-revision netwrix 1.0.7 +``` + +### Step 3: Monitor the Upgrade + +If auto-sync is enabled, ArgoCD automatically detects the revision change and begins deploying the new version. Monitor the status: + +```bash +# Watch ArgoCD application sync status +kubectl get apps -n argocd -w + +# Check DSPMctl status +dspmctl auto-status +``` + +If auto-sync is not enabled, manually trigger the sync: + +```bash +dspmctl sync netwrix.infra +dspmctl sync netwrix.core-api +``` + +### Step 4: Verify the Upgrade + +Confirm all applications are synced and healthy: + +```bash +kubectl get apps -n argocd +kubectl get pods -n access-analyzer +``` + +All applications should show `Synced` and `Healthy` status. All pods should be `Running` or `Completed`. + +## Rollback + +To revert to a previous version, set the target revision back: + +```bash +dspmctl set-revision netwrix +``` + +ArgoCD will redeploy the previous version. + +:::warning +Test upgrades in a non-production environment before applying to production systems. +::: diff --git a/docs/accessanalyzer/1.0/overview/_category_.json b/docs/accessanalyzer/1.0/overview/_category_.json new file mode 100644 index 0000000000..5015c8e965 --- /dev/null +++ b/docs/accessanalyzer/1.0/overview/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Overview", + "position": 10, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/overview/architecture.md b/docs/accessanalyzer/1.0/overview/architecture.md new file mode 100644 index 0000000000..56014309b5 --- /dev/null +++ b/docs/accessanalyzer/1.0/overview/architecture.md @@ -0,0 +1,69 @@ +--- +title: "Architecture Overview" +description: "Core components and how they work together" +sidebar_position: 20 +--- + +# Architecture Overview + +Access Analyzer runs as a set of containerized services on a single-node Kubernetes cluster (K3s), managed by ArgoCD for automated deployment and updates. + +## Component Architecture + +| Component | Technology | Purpose | +| --- | --- | --- | +| **Core API** | Ruby on Rails 8 | Business logic, REST API, session management | +| **Web Application** | React 18, TypeScript | User interface and dashboards | +| **Connector API** | Go | Manages connector execution as Kubernetes Jobs | +| **PostgreSQL** | v14.18 | Primary relational database for configuration and scan metadata | +| **ClickHouse** | v25.8.13 | Analytics database for scan results, logs, and traces | +| **Redis** | v8.4.0 | Session storage, job queues, and caching | +| **Metabase** | Embedded (airgap) | Dashboard and reporting engine | +| **Traefik** | Ingress controller | TLS termination and request routing | +| **ArgoCD** | v3.2.0 | GitOps-based application lifecycle management | +| **K3s** | v1.33.4 | Lightweight Kubernetes distribution | +| **OpenTelemetry** | Collector | Observability data pipeline (traces and logs) | +| **Prometheus** | v3.8.0 | Metrics collection and alerting | + +## Communication Flow + +Access Analyzer operates in three phases: + +### Phase 1 — Installation + +The installer deploys K3s and ArgoCD on the target VM. ArgoCD connects to the Netwrix OCI registry to pull application Helm charts. + +### Phase 2 — Application Sync + +ArgoCD deploys applications in ordered sync waves: + +| Wave | Components | +| --- | --- | +| **Wave -5** | Secrets initialization (auto-generated database passwords, API keys) | +| **Wave 1** | Infrastructure: PostgreSQL, ClickHouse, Redis, OpenTelemetry, Prometheus, Traefik | +| **Wave 2** | Core services: Core API, Web Application, Connector API, Metabase | +| **Wave 3** | Functions and database seeds | + +### Phase 3 — Ongoing Operations + +- **Traefik** routes incoming requests: `/api/` → Core API, `/metabase` → Metabase, `/` → Web Application +- **Core API** processes user requests and schedules scan jobs via Sidekiq (Redis-backed job queues) +- **Connector API** executes connectors as Kubernetes Jobs to scan data sources +- **Metabase** provides embedded dashboards with JWT-based single sign-on from Core API +- **ArgoCD** continuously monitors the OCI registry for updates and applies changes automatically + +## Namespace Layout + +| Namespace | Contents | +| --- | --- | +| `access-analyzer` | All application workloads (Core API, databases, connectors, Metabase, observability) | +| `argocd` | ArgoCD server, application controller, and repo server | +| `kube-system` | Traefik ingress controller, K3s system components | + +## Data Stores + +| Database | Data Stored | +| --- | --- | +| **PostgreSQL** | Users, sources, scans, service accounts, connector state, configuration | +| **ClickHouse** | Scan results, analytics, OpenTelemetry traces and logs | +| **Redis** | User sessions, Sidekiq job queues, application cache | diff --git a/docs/accessanalyzer/1.0/overview/keyconcepts.md b/docs/accessanalyzer/1.0/overview/keyconcepts.md new file mode 100644 index 0000000000..409c8cd341 --- /dev/null +++ b/docs/accessanalyzer/1.0/overview/keyconcepts.md @@ -0,0 +1,87 @@ +--- +title: "Key Concepts" +description: "Sources, scans, patterns, identities, and entitlements" +sidebar_position: 30 +--- + +# Key Concepts + +This page defines the core terminology used throughout Access Analyzer. + +## Sources + +A **source** is a data repository or identity provider that Access Analyzer connects to for scanning. Sources are organized into two categories: + +- **Data sources** — File shares (CIFS/SMB), SharePoint Online sites, and other storage locations containing files and data +- **IAM sources** — Identity providers such as Active Directory, Entra ID, and local groups that contain users, groups, and permissions + +Each source is associated with a [service account](#service-accounts) that provides the credentials needed for Access Analyzer to connect. + +## Source Groups + +A **source group** is a named collection of related sources that share a common service account and configuration. Source groups are created through the **Connect Source** wizard, which handles source creation, scan configuration, and scheduling in a single workflow. + +- **File Server** source groups can contain multiple servers (for example, all file servers in a department) +- **Active Directory** source groups can contain multiple domain controllers +- **Entra ID** source groups contain a single source (one Azure AD tenant) + +Source groups simplify management by letting you configure shared settings (service account, domain, scan options) once and apply them to all sources in the group. + +## Service Accounts + +A **service account** stores credentials used to authenticate with data sources and identity providers. Supported credential types include: + +- **Username / Password** — For Active Directory, CIFS/SMB file shares, and local groups +- **Client credentials (OAuth2)** — For Entra ID +- **Certificate** — For SharePoint Online + +Service accounts are managed in **Configuration** > **Service Accounts** and can be shared across multiple sources. + +## Connectors + +A **connector** is the component that performs the actual work of communicating with a source. Each source type has a corresponding connector that handles: + +- **Test connection** — Validates that credentials and network connectivity are correct +- **Access scan / sync** — Enumerates files, folders, permissions, or identities +- **Get object** — Retrieves specific objects or metadata + +Connectors are executed as Kubernetes Jobs and managed by the Connector API. + +## Scans + +A **scan** defines what to analyze and how. Access Analyzer supports several scan types: + +- **Access scans** — Enumerate files, folders, and permissions on data sources to identify who has access to what +- **Sensitive data scans** — Classify file contents against detection patterns to find PII, credentials, PHI, and financial records +- **Identity sync scans** — Synchronize users, groups, and roles from IAM sources (Active Directory Inventory, Entra ID Users/Groups/Roles) +- **Local Users and Groups scans** — Collect local account data from file servers (auto-created when an access scan is enabled) + +Scans are configured during the [Connect Source wizard](/docs/accessanalyzer/1_0/gettingstarted/firstscan/configuringscan) and can be run on demand or scheduled with a cron expression. Each scan run produces a **scan execution** record with status, duration, and results. + +## Identities and Entitlements + +- **Identity** — A user or group account from an IAM source (Active Directory, Entra ID, or local groups) +- **Entitlement** — A permission or access right granted to an identity on a data source (for example, read access to a file share) + +Access Analyzer maps identities to entitlements to show effective permissions and identify overly permissive access. + +## Sensitive Data Patterns + +A **pattern** is a detection rule used during sensitive data scans. Patterns match file content against regular expressions or classification models. Built-in patterns cover: + +- **PII** — Personally identifiable information (names, addresses, SSNs, etc.) +- **Credentials** — Passwords, API keys, tokens, and connection strings +- **PHI** — Protected health information +- **Financial Records** — Credit card numbers, bank accounts, financial data + +Patterns are organized into **taxonomies** — hierarchical groups of classification rules mapped to compliance frameworks (GDPR, CCPA, HIPAA, PCI DSS, GLBA, CMMC). + +## Dashboards + +**Dashboards** are pre-built Metabase visualizations that provide a summary view of your data security posture, including: + +- Sensitive data exposure by type and framework +- Access permission distribution +- Identity and group analysis + +Dashboards are embedded in the Access Analyzer web interface with single sign-on. diff --git a/docs/accessanalyzer/1.0/overview/overview.md b/docs/accessanalyzer/1.0/overview/overview.md new file mode 100644 index 0000000000..c74a5290d8 --- /dev/null +++ b/docs/accessanalyzer/1.0/overview/overview.md @@ -0,0 +1,36 @@ +--- +title: "What is Access Analyzer" +description: "Introduction to Netwrix Access Analyzer and its capabilities" +sidebar_position: 10 +--- + +# What is Access Analyzer + +Netwrix Access Analyzer is a Data Security Posture Management (DSPM) platform that discovers, classifies, and secures sensitive data across your organization's file systems and cloud services. It provides visibility into who has access to what data, identifies overly permissive access, and detects sensitive data exposure. + +## Core Capabilities + +- **Data Source Discovery** — Connect to file shares (CIFS/SMB), SharePoint Online sites, and other data repositories to inventory content and access permissions +- **Identity and Access Analysis** — Synchronize with Active Directory, Entra ID, and local groups to map identities, group memberships, and effective permissions +- **Sensitive Data Detection** — Scan files for PII, credentials, PHI, and financial records using built-in patterns and custom regex rules, with compliance mappings to GDPR, CCPA, HIPAA, PCI DSS, GLBA, and CMMC +- **Dashboards and Reporting** — View findings through embedded Metabase dashboards for data security posture, Active Directory insights, and sensitive data exposure +- **Audit Trail** — Maintain a full audit log of user actions and system events + +## How It Works + +1. **Configure data sources** — Add file shares, cloud services, and identity providers as data sources, each with an associated service account for authentication +2. **Run scans** — Create access scans to enumerate permissions and sensitive data scans to classify content +3. **Review findings** — Analyze results through dashboards, reports, and the scan execution history +4. **Take action** — Identify and remediate overly permissive access, exposed sensitive data, and policy violations + +## Deployment Model + +Access Analyzer is deployed as a self-contained Kubernetes cluster on a single Linux VM. A one-command installer provisions all required infrastructure — including K3s, ArgoCD, databases, and application services. Updates are managed automatically through ArgoCD GitOps. + +For installation instructions, see [Installation](/docs/accessanalyzer/1_0/install/overview). + +## What's Next + +- [Architecture Overview](/docs/accessanalyzer/1_0/overview/architecture) — Understand the platform components and how they interact +- [Key Concepts](/docs/accessanalyzer/1_0/overview/keyconcepts) — Learn the terminology used throughout Access Analyzer +- [Getting Started](/docs/accessanalyzer/1_0/gettingstarted/overview) — Begin configuring your first data source and scan diff --git a/docs/accessanalyzer/1.0/requirements/_category_.json b/docs/accessanalyzer/1.0/requirements/_category_.json new file mode 100644 index 0000000000..2047289ac1 --- /dev/null +++ b/docs/accessanalyzer/1.0/requirements/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Requirements", + "position": 30, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/requirements/connectors/_category_.json b/docs/accessanalyzer/1.0/requirements/connectors/_category_.json new file mode 100644 index 0000000000..4616c42c8c --- /dev/null +++ b/docs/accessanalyzer/1.0/requirements/connectors/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Connector Requirements", + "position": 30, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "cifs" + } +} diff --git a/docs/accessanalyzer/1.0/requirements/connectors/activedirectory.md b/docs/accessanalyzer/1.0/requirements/connectors/activedirectory.md new file mode 100644 index 0000000000..2ef3c03a17 --- /dev/null +++ b/docs/accessanalyzer/1.0/requirements/connectors/activedirectory.md @@ -0,0 +1,45 @@ +--- +title: "Active Directory" +description: "LDAP connectivity, service account permissions, and network ports" +sidebar_position: 30 +--- + +# Active Directory + +The Active Directory connector synchronizes users, groups, and group memberships from Active Directory into Access Analyzer. It uses the LDAP protocol for communication. + +## Network Requirements + +| Port | Protocol | Direction | Description | +| --- | --- | --- | --- | +| 389 | TCP | Access Analyzer → Domain Controller | LDAP | +| 636 | TCP | Access Analyzer → Domain Controller | LDAPS (LDAP over SSL) | + +## Service Account Requirements + +The connector requires a domain service account with the following: + +| Requirement | Details | +| --- | --- | +| **Account type** | Domain user account | +| **Authentication** | Username and password | +| **Minimum permissions** | Read access to directory objects (users, groups, OUs) | +| **Recommended group** | Domain Users (or equivalent read-only access) | + +:::note +The service account does not require Domain Admin or any write permissions. Read-only access to directory objects is sufficient for identity synchronization. +::: + +## Credential Type + +| Field | Value | +| --- | --- | +| **Type** | Username / Password | +| **Username format** | `DOMAIN\username` or `username@domain.com` | + +## Connector Capabilities + +| Operation | Description | +| --- | --- | +| **Test connection** | Validates LDAP connectivity and credential authentication | +| **Sync** | Full synchronization of users, groups, and group memberships | diff --git a/docs/accessanalyzer/1.0/requirements/connectors/cifs.md b/docs/accessanalyzer/1.0/requirements/connectors/cifs.md new file mode 100644 index 0000000000..a5ade15dbd --- /dev/null +++ b/docs/accessanalyzer/1.0/requirements/connectors/cifs.md @@ -0,0 +1,52 @@ +--- +title: "CIFS / SMB File Share" +description: "Supported platforms, permissions, and network ports for CIFS/SMB scanning" +sidebar_position: 10 +--- + +# CIFS / SMB File Share + +The CIFS/SMB connector scans Windows file shares to enumerate files, folders, and access permissions. It supports SMBv2 and SMBv3 protocols with concurrent scanning workers. + +## Network Requirements + +| Port | Protocol | Direction | Description | +| --- | --- | --- | --- | +| 445 | TCP | Access Analyzer → File Server | SMB file sharing | + +## Service Account Requirements + +| Requirement | Details | +| --- | --- | +| **Account type** | Domain or local user account on the file server | +| **Authentication** | Username and password | +| **Minimum permissions** | Read access and list permissions on target shares | +| **Domain** | Required if the file server is domain-joined | + +:::note +The service account needs read-only access to the shares and folders being scanned. It does not require write, modify, or administrative permissions. +::: + +## Credential Type + +| Field | Value | +| --- | --- | +| **Type** | Username / Password | +| **Username format** | `DOMAIN\username` or local account name | + +## Connector Capabilities + +| Operation | Description | +| --- | --- | +| **Test connection** | Validates SMB connectivity and authentication | +| **Access scan** | Enumerates files, folders, and permissions with configurable worker concurrency (1–20) | +| **Get object** | Retrieves specific file or folder metadata | + +## Scan Configuration Options + +| Option | Description | +| --- | --- | +| **Share filtering** | Include or exclude specific shares | +| **Scan depth** | Maximum folder depth to traverse | +| **Worker concurrency** | Number of parallel scanning threads (1–20) | +| **Pause / Resume** | Scans can be paused and resumed | diff --git a/docs/accessanalyzer/1.0/requirements/connectors/entraid.md b/docs/accessanalyzer/1.0/requirements/connectors/entraid.md new file mode 100644 index 0000000000..11dfb77943 --- /dev/null +++ b/docs/accessanalyzer/1.0/requirements/connectors/entraid.md @@ -0,0 +1,54 @@ +--- +title: "Entra ID" +description: "Azure App Registration, Graph API permissions, and OAuth2 credentials" +sidebar_position: 40 +--- + +# Entra ID + +The Entra ID connector validates connectivity to Microsoft Entra ID (formerly Azure Active Directory) using OAuth2 client credentials. + +:::note +In Access Analyzer v1.0, the Entra ID connector supports **test connection only**. Full identity synchronization is not available in this release. +::: + +## Network Requirements + +| Port | Protocol | Direction | Description | +| --- | --- | --- | --- | +| 443 | TCP | Access Analyzer → Microsoft identity platform | HTTPS | + +## Azure App Registration + +An Azure AD (Entra ID) app registration is required. + +### Required API Permissions + +| Permission | Type | Description | +| --- | --- | --- | +| `User.Read.All` | Application | Read all user profiles (for future sync capability) | +| `Group.Read.All` | Application | Read all group memberships (for future sync capability) | + +### Registration Steps + +1. Sign in to the [Azure portal](https://portal.azure.com) and navigate to **Microsoft Entra ID** > **App registrations** +2. Click **New registration** and provide a name +3. Under **API permissions**, add the required Microsoft Graph application permissions +4. Grant admin consent for the permissions +5. Under **Certificates & secrets**, create a client secret +6. Note the **Application (client) ID**, **Tenant ID**, and **Client Secret** + +## Credential Type + +| Field | Value | +| --- | --- | +| **Type** | OAuth2 Client Credentials | +| **Client ID** | Application (client) ID | +| **Client Secret** | Client secret value | +| **Tenant ID** | Directory (tenant) ID | + +## Connector Capabilities + +| Operation | Description | +| --- | --- | +| **Test connection** | Validates OAuth2 authentication and Graph API connectivity | diff --git a/docs/accessanalyzer/1.0/requirements/connectors/localgroups.md b/docs/accessanalyzer/1.0/requirements/connectors/localgroups.md new file mode 100644 index 0000000000..ac5efd6ad9 --- /dev/null +++ b/docs/accessanalyzer/1.0/requirements/connectors/localgroups.md @@ -0,0 +1,52 @@ +--- +title: "Local Groups" +description: "PowerShell Remoting and target machine permissions" +sidebar_position: 50 +--- + +# Local Groups + +The Local Groups connector enumerates local users and group memberships on Windows machines using PowerShell Remoting (WinRM). + +## Network Requirements + +| Port | Protocol | Direction | Description | +| --- | --- | --- | --- | +| 5985 | TCP | Access Analyzer → Target Machine | WinRM over HTTP | +| 5986 | TCP | Access Analyzer → Target Machine | WinRM over HTTPS | + +## Service Account Requirements + +| Requirement | Details | +| --- | --- | +| **Account type** | Local administrator or member of Remote Management Users group | +| **Authentication** | Username and password | +| **WinRM** | PowerShell Remoting must be enabled on target machines | + +## Enabling WinRM on Target Machines + +PowerShell Remoting must be enabled on each target machine: + +```powershell +Enable-PSRemoting -Force +``` + +For domain-joined machines, this can be configured via Group Policy: + +1. Open **Group Policy Management** +2. Navigate to **Computer Configuration** > **Administrative Templates** > **Windows Components** > **Windows Remote Management (WinRM)** > **WinRM Service** +3. Enable **Allow remote server management through WinRM** + +## Credential Type + +| Field | Value | +| --- | --- | +| **Type** | Username / Password | +| **Username format** | `MACHINE\username` or `DOMAIN\username` | + +## Connector Capabilities + +| Operation | Description | +| --- | --- | +| **Test connection** | Validates WinRM connectivity and authentication | +| **Sync** | Enumerates local users, groups, and group memberships | diff --git a/docs/accessanalyzer/1.0/requirements/connectors/sharepointonline.md b/docs/accessanalyzer/1.0/requirements/connectors/sharepointonline.md new file mode 100644 index 0000000000..4e06241002 --- /dev/null +++ b/docs/accessanalyzer/1.0/requirements/connectors/sharepointonline.md @@ -0,0 +1,57 @@ +--- +title: "SharePoint Online" +description: "Azure App Registration, Graph API permissions, and certificate authentication" +sidebar_position: 20 +--- + +# SharePoint Online + +The SharePoint Online connector scans SharePoint sites to enumerate content and access permissions using the Microsoft Graph API with certificate-based authentication. + +## Network Requirements + +| Port | Protocol | Direction | Description | +| --- | --- | --- | --- | +| 443 | TCP | Access Analyzer → Microsoft Graph API | HTTPS | + +## Azure App Registration + +An Azure AD (Entra ID) app registration is required for SharePoint Online connectivity. + +### Required API Permissions + +| Permission | Type | Description | +| --- | --- | --- | +| `Sites.Read.All` | Application | Read items in all site collections | + +### Registration Steps + +1. Sign in to the [Azure portal](https://portal.azure.com) and navigate to **Microsoft Entra ID** > **App registrations** +2. Click **New registration** and provide a name (for example, `Netwrix Access Analyzer - SharePoint`) +3. Under **API permissions**, add the **Microsoft Graph** application permission `Sites.Read.All` +4. Grant admin consent for the permission +5. Under **Certificates & secrets**, upload a certificate (`.cer` or `.pem` public key) +6. Note the **Application (client) ID** and **Tenant ID** + +## Credential Type + +| Field | Value | +| --- | --- | +| **Type** | Certificate | +| **Client ID** | Application (client) ID from the app registration | +| **Tenant ID** | Directory (tenant) ID | +| **Certificate** | Private key file (`.pem`) corresponding to the uploaded public key | + +## Connector Capabilities + +| Operation | Description | +| --- | --- | +| **Test connection** | Validates Graph API connectivity and certificate authentication | +| **Access scan** | Enumerates SharePoint sites, document libraries, files, and permissions | +| **Get object** | Retrieves specific site or document metadata | + +## Scan Configuration Options + +| Option | Description | +| --- | --- | +| **Site filtering** | Include or exclude specific SharePoint sites | diff --git a/docs/accessanalyzer/1.0/requirements/database/_category_.json b/docs/accessanalyzer/1.0/requirements/database/_category_.json new file mode 100644 index 0000000000..32e43edc04 --- /dev/null +++ b/docs/accessanalyzer/1.0/requirements/database/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Database Requirements", + "position": 20, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "postgresql" + } +} diff --git a/docs/accessanalyzer/1.0/requirements/database/clickhouse.md b/docs/accessanalyzer/1.0/requirements/database/clickhouse.md new file mode 100644 index 0000000000..868c10e9da --- /dev/null +++ b/docs/accessanalyzer/1.0/requirements/database/clickhouse.md @@ -0,0 +1,30 @@ +--- +title: "ClickHouse" +description: "ClickHouse version and configuration" +sidebar_position: 20 +--- + +# ClickHouse + +ClickHouse is a columnar analytics database used by Access Analyzer for scan results, reporting data, and observability (OpenTelemetry traces and logs). + +## Version + +| Component | Value | +| --- | --- | +| **ClickHouse version** | 25.8.13 | +| **Namespace** | `access-analyzer` | +| **HTTP interface port** | 8123 | +| **Native protocol port** | 9000 | + +## Provisioning + +ClickHouse is **automatically provisioned** by the installer. No manual setup is required. + +Database passwords are auto-generated and stored as Kubernetes secrets. + +## Data Stored + +- Scan results and analytics data +- OpenTelemetry traces and logs (via the `access_analyzer_logs` database) +- Reporting and dashboard data queried by Metabase diff --git a/docs/accessanalyzer/1.0/requirements/database/postgresql.md b/docs/accessanalyzer/1.0/requirements/database/postgresql.md new file mode 100644 index 0000000000..4e5f9dba79 --- /dev/null +++ b/docs/accessanalyzer/1.0/requirements/database/postgresql.md @@ -0,0 +1,40 @@ +--- +title: "PostgreSQL" +description: "PostgreSQL version and configuration" +sidebar_position: 10 +--- + +# PostgreSQL + +PostgreSQL serves as the primary relational database for Access Analyzer, storing configuration, user accounts, scan metadata, connector state, and application data. + +## Version + +| Component | Value | +| --- | --- | +| **PostgreSQL version** | 14.18 | +| **Namespace** | `access-analyzer` | + +## Provisioning + +PostgreSQL is **automatically provisioned** by the installer. No manual database setup, schema creation, or user configuration is required. + +The installer creates the following database users during deployment: + +| User | Purpose | +| --- | --- | +| `postgres` | Superuser for administrative tasks | +| `connector_readonly` | Read-only access for connector queries | +| `connector_execution_update` | Write access for connector execution state | +| `connector_state_readwrite` | Read/write access for connector state management | + +All database passwords are auto-generated by the `dspm-utility` secret initialization process and stored as Kubernetes secrets. + +## Data Stored + +- User accounts and authentication +- Source and scan configuration +- Service accounts (encrypted credentials) +- Connector state and execution metadata +- Application settings and feature flags +- Audit log entries diff --git a/docs/accessanalyzer/1.0/requirements/database/redis.md b/docs/accessanalyzer/1.0/requirements/database/redis.md new file mode 100644 index 0000000000..9cc26151cb --- /dev/null +++ b/docs/accessanalyzer/1.0/requirements/database/redis.md @@ -0,0 +1,43 @@ +--- +title: "Redis" +description: "Redis version and configuration" +sidebar_position: 30 +--- + +# Redis + +Redis provides in-memory caching, session storage, and job queue management for Access Analyzer. + +## Version + +| Component | Value | +| --- | --- | +| **Redis version** | 8.4.0 | +| **Namespace** | `access-analyzer` | +| **Port** | 6379 | + +## Provisioning + +Redis is **automatically provisioned** by the installer. No manual setup is required. + +## Data Stored + +| Function | Description | +| --- | --- | +| **User sessions** | Session data for authenticated users (with IP validation and configurable TTL) | +| **Sidekiq job queues** | Background job processing for scans, syncs, mailers, and system tasks | +| **Application cache** | Frequently accessed data for reduced database load | + +## Job Queues + +Redis backs the Sidekiq job processing system, which uses the following queues: + +| Queue | Purpose | +| --- | --- | +| `critical` | High-priority system operations | +| `scans` | Scan execution jobs | +| `syncs` | Identity synchronization jobs | +| `scheduler` | Scheduled job dispatch | +| `default` | General-purpose jobs | +| `mailers` | Email notification delivery | +| `low` | Low-priority background tasks | diff --git a/docs/accessanalyzer/1.0/requirements/overview.md b/docs/accessanalyzer/1.0/requirements/overview.md new file mode 100644 index 0000000000..84fa865f34 --- /dev/null +++ b/docs/accessanalyzer/1.0/requirements/overview.md @@ -0,0 +1,35 @@ +--- +title: "Requirements" +description: "System, database, and connector requirements for Access Analyzer" +sidebar_position: 1 +--- + +# Requirements + +This section covers all prerequisites for deploying and operating Netwrix Access Analyzer. + +## System Requirements + +The Access Analyzer VM must meet minimum hardware, operating system, and kernel requirements. The installer validates these automatically during [preflight checks](/docs/accessanalyzer/1_0/install/preflight). + +- [Kubernetes and Operating System](/docs/accessanalyzer/1_0/requirements/system/kubernetes) — OS version, kernel, and K3s details +- [Hardware and Resource Allocation](/docs/accessanalyzer/1_0/requirements/system/hardware) — CPU, memory, disk, and virtualization +- [Network and Port Requirements](/docs/accessanalyzer/1_0/requirements/system/network) — Outbound endpoints, internal ports, and firewall rules + +## Database Requirements + +All databases are automatically provisioned by the installer. No manual database setup is required. + +- [PostgreSQL](/docs/accessanalyzer/1_0/requirements/database/postgresql) — Primary relational database +- [ClickHouse](/docs/accessanalyzer/1_0/requirements/database/clickhouse) — Analytics and observability database +- [Redis](/docs/accessanalyzer/1_0/requirements/database/redis) — Session cache and job queues + +## Connector Requirements + +Each connector type has specific requirements for authentication, network access, and permissions on the target system. + +- [CIFS / SMB File Share](/docs/accessanalyzer/1_0/requirements/connectors/cifs) — SMB file share scanning +- [SharePoint Online](/docs/accessanalyzer/1_0/requirements/connectors/sharepointonline) — SharePoint site scanning +- [Active Directory](/docs/accessanalyzer/1_0/requirements/connectors/activedirectory) — AD identity synchronization +- [Entra ID](/docs/accessanalyzer/1_0/requirements/connectors/entraid) — Entra ID connection testing +- [Local Groups](/docs/accessanalyzer/1_0/requirements/connectors/localgroups) — Local group enumeration diff --git a/docs/accessanalyzer/1.0/requirements/system/_category_.json b/docs/accessanalyzer/1.0/requirements/system/_category_.json new file mode 100644 index 0000000000..950fb05a5f --- /dev/null +++ b/docs/accessanalyzer/1.0/requirements/system/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "System Requirements", + "position": 10, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "kubernetes" + } +} diff --git a/docs/accessanalyzer/1.0/requirements/system/hardware.md b/docs/accessanalyzer/1.0/requirements/system/hardware.md new file mode 100644 index 0000000000..7787c810de --- /dev/null +++ b/docs/accessanalyzer/1.0/requirements/system/hardware.md @@ -0,0 +1,84 @@ +--- +title: "Hardware and Resource Allocation" +description: "CPU, memory, storage, and virtualization requirements" +sidebar_position: 20 +--- + +# Hardware and Resource Allocation + +Access Analyzer is deployed on a single Linux virtual machine. This page details the hardware requirements and virtualization configuration. + +## Deployment Sizing + +| Size | CPU | Memory | Disk | Use Case | +| --- | --- | --- | --- | --- | +| **Small** | 2 vCPUs (4 recommended) | 8 GB (16 GB recommended) | 20 GB free (50 GB recommended) | Evaluation and small environments | +| **Medium** | 8 vCPUs | 32 GB | 100 GB SSD | Mid-size environments | +| **Large** | 16 vCPUs | 64 GB | 500 GB SSD | Large enterprise environments | + +All sizes require SSD or NVMe storage for optimal database performance. + +## Disk Space by Directory + +| Path | Minimum Free Space | Purpose | +| --- | --- | --- | +| `/` | 20 GB | Root filesystem | +| `/var` | 20 GB | K3s data, containers, logs | +| `/var/lib` | 20 GB | K3s data directory | +| `/var/log` | 5 GB | System and application logs | +| `/etc` | 1 GB | Configuration files | + +## Virtualization Requirements + +When running on a hypervisor, the following must be supported: + +| Requirement | Details | +| --- | --- | +| **Linux namespaces** | NET, PID, IPC, UTS, MNT, USER | +| **Control groups** | cgroups v1 or v2 with memory and CPU controllers | +| **Overlay filesystem** | Kernel module for container layers | +| **iptables** | Kubernetes networking | + +## Hypervisor Configuration + +Configure **static memory allocation** for the Access Analyzer VM. Dynamic or ballooned memory can cause resource underestimation and out-of-memory conditions. + +### VMware vSphere / ESXi + +Disable memory ballooning: + +``` +sched.mem.pshare.enable = "FALSE" +mem.balloon.enable = "FALSE" +``` + +Set these in **VM Settings** > **VM Options** > **Advanced** > **Edit Configuration**. + +### Microsoft Hyper-V + +Use static memory: + +```powershell +Set-VMMemory -VMName "" -DynamicMemoryEnabled $false -StartupBytes 16GB +``` + +### KVM / QEMU + +Use hugepages: + +```xml + + + +``` + +## Swap + +| System Memory | Recommendation | +| --- | --- | +| 16 GB or more | Swap is optional | +| Less than 16 GB | 2–4 GB swap recommended to prevent OOM during container pulls | + +## Resource Scaling + +The installer supports a `--size` flag (1–10) that scales memory thresholds by the specified multiplier. For example, `--size 2` doubles the minimum and recommended memory requirements. See [Environment Variables](/docs/accessanalyzer/1_0/install/environmentvariables). diff --git a/docs/accessanalyzer/1.0/requirements/system/kubernetes.md b/docs/accessanalyzer/1.0/requirements/system/kubernetes.md new file mode 100644 index 0000000000..fb62a394f0 --- /dev/null +++ b/docs/accessanalyzer/1.0/requirements/system/kubernetes.md @@ -0,0 +1,53 @@ +--- +title: "Kubernetes and Operating System" +description: "OS version, kernel requirements, and K3s Kubernetes details" +sidebar_position: 10 +--- + +# Kubernetes and Operating System + +Access Analyzer uses K3s, a lightweight Kubernetes distribution, which is automatically deployed by the installer. No manual Kubernetes setup is required. + +## Operating System + +| Requirement | Value | +| --- | --- | +| **Distribution** | Ubuntu 24.04 LTS | +| **Architecture** | x86_64 (amd64) | +| **Kernel version** | 5.15 or later | + +:::note +Other Linux distributions may work but are not officially tested or supported. Ubuntu 24.04 LTS is the recommended and validated platform. +::: + +## K3s Kubernetes + +| Component | Version | +| --- | --- | +| **K3s** | v1.33.4+k3s1 | +| **Kubeconfig mode** | `644` | +| **Secrets encryption** | Enabled (at rest) | +| **Service name** | `k3s-dspm` | + +K3s is installed and managed automatically by the Access Analyzer installer. The `kubectl` command is available immediately after installation for cluster management. + +## Kernel Features + +The following kernel features must be available. The installer [preflight checks](/docs/accessanalyzer/1_0/install/preflight) validate these automatically: + +| Feature | Description | +| --- | --- | +| **cgroups v1 or v2** | Memory and CPU controllers required for container resource management | +| **Overlay filesystem** | `overlay` kernel module for container image layers | +| **Linux namespaces** | NET, PID, IPC, UTS, MNT, USER for container isolation | +| **iptables** | Required for Kubernetes networking and service routing | + +## ArgoCD + +| Component | Version | +| --- | --- | +| **ArgoCD** | v3.2.0 | +| **Namespace** | `argocd` | +| **UI port** | 8090 (via port-forward) | + +ArgoCD is deployed automatically and manages the lifecycle of all Access Analyzer application components through GitOps. diff --git a/docs/accessanalyzer/1.0/requirements/system/network.md b/docs/accessanalyzer/1.0/requirements/system/network.md new file mode 100644 index 0000000000..f3c04090b4 --- /dev/null +++ b/docs/accessanalyzer/1.0/requirements/system/network.md @@ -0,0 +1,64 @@ +--- +title: "Network and Port Requirements" +description: "Required network ports, outbound endpoints, and firewall rules" +sidebar_position: 30 +--- + +# Network and Port Requirements + +Access Analyzer requires outbound internet access during installation and operation, and specific internal ports for service communication. + +## Outbound Endpoints (Internet) + +The following endpoints must be reachable over HTTPS (port 443): + +| Endpoint | Purpose | When Required | +| --- | --- | --- | +| `get.k3s.io` | K3s installer download | Installation only | +| `raw.githubusercontent.com` | ArgoCD manifests | Installation only | +| `oci.pkg.keygen.sh` | Netwrix OCI registry (Helm charts, application images) | Installation and updates | +| `docker.io` / `docker.com` | Container base images | Installation and updates | + +## Internal Ports + +These ports are used within the Access Analyzer VM for service-to-service communication: + +| Port | Protocol | Service | Description | +| --- | --- | --- | --- | +| 443 | TCP | Traefik | HTTPS ingress for web UI and API | +| 6443 | TCP | K3s API | Kubernetes API server | +| 8090 | TCP | ArgoCD | ArgoCD UI (via port-forward) | +| 5432 | TCP | PostgreSQL | Database connections | +| 8123 | TCP | ClickHouse | HTTP interface | +| 9000 | TCP | ClickHouse | Native protocol | +| 6379 | TCP | Redis | Cache and queue connections | + +:::note +All internal ports are bound to the local cluster network. Only port 443 (Traefik) is exposed externally for the web interface. +::: + +## Connector Network Requirements + +Depending on the connectors you configure, the Access Analyzer VM must also have outbound access to your data sources: + +| Connector | Target Port | Protocol | Notes | +| --- | --- | --- | --- | +| CIFS / SMB | 445 | TCP | SMB file shares | +| Active Directory | 389 / 636 | TCP | LDAP / LDAPS | +| SharePoint Online | 443 | TCP | Microsoft Graph API | +| Entra ID | 443 | TCP | Microsoft identity platform | +| Local Groups | 5985 / 5986 | TCP | WinRM (HTTP / HTTPS) | + +## Proxy Configuration + +If outbound traffic is routed through a proxy, set the following environment variables before running the installer: + +```bash +export HTTP_PROXY="http://:" +export HTTPS_PROXY="http://:" +export NO_PROXY="localhost,127.0.0.1,10.0.0.0/8" +``` + +## Firewall Configuration + +See [Network Configuration](/docs/accessanalyzer/1_0/install/network) for firewall rule examples for Azure, AWS, and on-premises environments. diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/_category_.json b/docs/accessanalyzer/1.0/sensitivedatadiscovery/_category_.json new file mode 100644 index 0000000000..6bf6249468 --- /dev/null +++ b/docs/accessanalyzer/1.0/sensitivedatadiscovery/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Sensitive Data Discovery", + "position": 70, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/overview.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/overview.md new file mode 100644 index 0000000000..f534a637e7 --- /dev/null +++ b/docs/accessanalyzer/1.0/sensitivedatadiscovery/overview.md @@ -0,0 +1,32 @@ +--- +title: "Sensitive Data Discovery" +description: "Discover and classify sensitive data across your environment" +sidebar_position: 1 +--- + +# Sensitive Data Discovery + +Sensitive Data Discovery (SDD) in Netwrix Access Analyzer identifies and classifies sensitive information across your connected data sources. The platform uses two complementary detection methods: the Netwrix Data Classification SDK and custom regex pattern matching. + +## Workflow + +Follow these steps to discover sensitive data in your environment: + +1. **Configure detection patterns** — Select from [built-in patterns](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/builtinpatterns) or [create custom regex patterns](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/custompatterns) to define what constitutes sensitive data. +2. **Organize patterns into groups** — Use [pattern groups](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/patterngroups) to logically categorize your detection patterns. +3. **Map to compliance frameworks** — Configure [taxonomy groups](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/taxonomygroups) and [classification rules](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/classificationrules) to align findings with regulatory requirements. +4. **Run a scan** — [Execute a sensitive data scan](/docs/accessanalyzer/1_0/sensitivedatadiscovery/runningscan) against your target data sources. +5. **Review results** — Analyze [match counts](/docs/accessanalyzer/1_0/sensitivedatadiscovery/reviewingresults/matchcounts) and [classification breakdowns](/docs/accessanalyzer/1_0/sensitivedatadiscovery/reviewingresults/classificationbreakdown) to understand your data risk posture. + +## Supported Data Types + +| Category | Examples | +| --- | --- | +| PII | Social Security numbers, names, addresses, email addresses | +| Credentials | Passwords, API keys, authentication tokens | +| PHI | Medical records, health data, insurance identifiers | +| Financial Records | Credit card numbers, bank account details | + +:::note +Sensitive data scans are configured during the scan creation wizard. Ensure your detection patterns and taxonomy mappings are in place before running your first scan. +::: diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/_category_.json b/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/_category_.json new file mode 100644 index 0000000000..868656ec39 --- /dev/null +++ b/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Configuring Patterns", + "position": 20, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "builtinpatterns" + } +} diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/builtinpatterns.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/builtinpatterns.md new file mode 100644 index 0000000000..0653231675 --- /dev/null +++ b/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/builtinpatterns.md @@ -0,0 +1,34 @@ +--- +title: "Built-in Patterns" +description: "Pre-configured patterns for PII, PCI, SSN, and more" +sidebar_position: 10 +--- + +# Built-in Patterns + +Netwrix Access Analyzer ships with a library of pre-configured detection patterns that identify common categories of sensitive data. These built-in patterns use the Netwrix Data Classification SDK and are ready to use without additional configuration. + +## Pattern Categories + +| Category | Description | Examples | +| --- | --- | --- | +| PII | Personally identifiable information | Social Security numbers, full names, mailing addresses, email addresses, phone numbers | +| Credentials | Authentication and access secrets | Passwords, API keys, tokens, private keys, connection strings | +| PHI | Protected health information | Medical record numbers, health plan IDs, diagnosis codes, lab results | +| Financial Records | Payment and banking data | Credit card numbers (PAN), bank account and routing numbers, tax IDs | + +## How Built-in Patterns Work + +Built-in patterns leverage two detection methods: + +- **Netwrix Data Classification SDK** — A C#/.NET-based engine that applies advanced heuristics and contextual analysis beyond simple pattern matching. +- **Regex pattern matching** — Standard regular expressions tuned for high-accuracy detection of structured data formats such as SSNs, credit card numbers, and IBANs. + +:::note +Built-in patterns cannot be edited directly. To modify detection behavior, create a [custom pattern](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/custompatterns) and organize it into a [pattern group](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/patterngroups). +::: + +## Next Steps + +- [Create custom regex patterns](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/custompatterns) for organization-specific data formats +- [Organize patterns into groups](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/patterngroups) for streamlined scan configuration diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/custompatterns.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/custompatterns.md new file mode 100644 index 0000000000..8645e34568 --- /dev/null +++ b/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/custompatterns.md @@ -0,0 +1,47 @@ +--- +title: "Creating Custom Regex Patterns" +description: "Define custom regex patterns for sensitive data detection" +sidebar_position: 20 +--- + +# Creating Custom Regex Patterns + +Custom regex patterns allow you to extend sensitive data detection beyond the built-in library. Define patterns that match organization-specific data formats such as internal account numbers, proprietary identifiers, or region-specific document formats. + +## Creating a Custom Pattern + +To create a custom regex pattern: + +1. Navigate to the **Sensitive Data Discovery** section in Access Analyzer. +2. Select **Patterns** and click **Add Pattern**. +3. Provide a **Name** and optional **Description** for the pattern. +4. Enter the **Regex Expression** that defines the match criteria. +5. Select the appropriate **Category** (PII, Credentials, PHI, or Financial Records). +6. Click **Save** to register the pattern. + +:::note +Custom patterns can also be added programmatically via the Access Analyzer API. Refer to the API documentation for endpoint details and payload format. +::: + +## Regex Best Practices + +- **Be specific** — Overly broad patterns increase false positives. Use anchors, character classes, and quantifiers to narrow matches. +- **Test before deploying** — Validate your regex against sample data to confirm it captures the intended formats without excessive noise. +- **Use named groups** — Where supported, named capture groups improve readability and facilitate downstream processing. + +## Example + +A pattern to detect a custom internal employee ID formatted as `EMP-` followed by six digits: + +``` +EMP-\d{6} +``` + +:::warning +Poorly constructed regex patterns may degrade scan performance. Avoid unbounded quantifiers and excessive backtracking in pattern definitions. +::: + +## Next Steps + +- [Organize patterns into groups](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/patterngroups) for easier management +- [Map patterns to compliance frameworks](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/taxonomygroups) using taxonomy groups diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/patterngroups.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/patterngroups.md new file mode 100644 index 0000000000..9643c03154 --- /dev/null +++ b/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/patterngroups.md @@ -0,0 +1,39 @@ +--- +title: "Pattern Groups" +description: "Organizing patterns into logical groups" +sidebar_position: 30 +--- + +# Pattern Groups + +Pattern groups organize individual detection patterns into logical collections. Grouping patterns by category or purpose simplifies scan configuration and makes it easier to apply consistent detection policies across multiple scans. + +## How Pattern Groups Work + +A pattern group is a named container that holds one or more detection patterns (built-in or custom). When you configure a sensitive data scan, you select pattern groups rather than individual patterns, which reduces configuration complexity. + +Common grouping strategies include: + +- **By data type** — Group all PII patterns together, all credential patterns together, and so on. +- **By compliance framework** — Group patterns that satisfy a specific regulation such as HIPAA or PCI DSS. +- **By business unit** — Group patterns relevant to a particular department or data domain. + +## Managing Pattern Groups + +To create or edit a pattern group: + +1. Navigate to **Sensitive Data Discovery** > **Patterns**. +2. Select the **Pattern Groups** tab. +3. Click **Add Group** to create a new group, or select an existing group to edit it. +4. Provide a **Name** and optional **Description**. +5. Add or remove patterns from the group using the pattern selector. +6. Click **Save**. + +:::note +A single pattern can belong to multiple groups. Changes to a pattern are reflected in all groups that reference it. +::: + +## Next Steps + +- [Configure taxonomy groups](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/taxonomygroups) to map pattern groups to compliance frameworks +- [Run a sensitive data scan](/docs/accessanalyzer/1_0/sensitivedatadiscovery/runningscan) using your configured pattern groups diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/_category_.json b/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/_category_.json new file mode 100644 index 0000000000..8d68d0c5ea --- /dev/null +++ b/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Reviewing Results", + "position": 50, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "matchcounts" + } +} diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/classificationbreakdown.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/classificationbreakdown.md new file mode 100644 index 0000000000..74a5711b20 --- /dev/null +++ b/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/classificationbreakdown.md @@ -0,0 +1,43 @@ +--- +title: "Classification Breakdown" +description: "Analyzing results by classification category" +sidebar_position: 20 +--- + +# Classification Breakdown + +The classification breakdown view organizes sensitive data scan results by taxonomy group and compliance framework. This view helps you assess regulatory exposure and prioritize remediation efforts based on the frameworks most relevant to your organization. + +## Viewing the Breakdown + +To access the classification breakdown: + +1. Navigate to the **Scans** section and select a completed scan. +2. Open the **Results** tab. +3. Select the **Classification Breakdown** view. + +The breakdown displays a summary of matches grouped by each applicable compliance framework. + +## Framework Summary + +| Column | Description | +| --- | --- | +| **Framework** | The compliance standard (GDPR, CCPA, HIPAA, PCI DSS, GLBA, CMMC) | +| **Total Matches** | Aggregate count of sensitive data matches mapped to this framework | +| **Files Affected** | Number of distinct files containing matches for this framework | +| **Top Patterns** | The most frequently triggered detection patterns within the framework | + +## Interpreting Results + +- A file may appear under multiple frameworks if its contents match classification rules mapped to different taxonomy groups. +- The **Top Patterns** column highlights which data types contribute the most matches, helping you identify the most common exposure areas. +- Use the breakdown to generate framework-specific remediation plans by focusing on the frameworks with the highest match counts. + +:::note +Classification breakdown results depend on the [taxonomy groups](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/taxonomygroups) and [classification rules](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/classificationrules) configured at the time of the scan. Update your taxonomy mappings and re-scan to reflect new compliance requirements. +::: + +## Next Steps + +- [Export findings](/docs/accessanalyzer/1_0/dashboards/metabase/exportingdata) for compliance reporting +- [View dashboards](/docs/accessanalyzer/1_0/dashboards/overview) for a high-level risk summary diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/matchcounts.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/matchcounts.md new file mode 100644 index 0000000000..2dd3d19f26 --- /dev/null +++ b/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/matchcounts.md @@ -0,0 +1,46 @@ +--- +title: "Match Counts and Locations" +description: "Viewing match counts per file and location details" +sidebar_position: 10 +--- + +# Match Counts and Locations + +After a sensitive data scan completes, the results view displays match counts that summarize how many sensitive data instances were detected, organized by file, pattern, and compliance framework. + +## Understanding Match Counts + +Match counts are reported at three levels: + +| Level | Description | +| --- | --- | +| **Per File** | Total number of sensitive data matches found in each scanned file | +| **Per Pattern** | Number of matches attributed to each detection pattern (for example, SSN, credit card number) | +| **Per Framework** | Aggregate match count grouped by compliance framework (GDPR, HIPAA, PCI DSS, and others) | + +## Viewing Match Details + +To review match counts for a completed scan: + +1. Navigate to the **Scans** section and select the completed scan. +2. Open the **Results** tab to view the summary. +3. Use the **Files** view to see match counts per file, sorted by the number of matches in descending order. +4. Click on a specific file to view the individual pattern matches detected within it. +5. Use the **Patterns** view to see total matches per detection pattern across all scanned files. + +:::note +Match counts reflect the number of pattern matches, not the number of unique sensitive data values. A single file containing the same SSN in multiple locations is counted as multiple matches. +::: + +## Filtering Results + +Use the filter controls to narrow results by: + +- **Data type** — PII, Credentials, PHI, or Financial Records +- **Pattern group** — Filter by a specific pattern group applied during the scan +- **Severity** — Focus on high-priority findings + +## Next Steps + +- [View classification breakdowns](/docs/accessanalyzer/1_0/sensitivedatadiscovery/reviewingresults/classificationbreakdown) to analyze results by compliance framework +- [Access dashboards](/docs/accessanalyzer/1_0/dashboards/overview) for a visual summary of findings diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/runningscan.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/runningscan.md new file mode 100644 index 0000000000..78306fe3bc --- /dev/null +++ b/docs/accessanalyzer/1.0/sensitivedatadiscovery/runningscan.md @@ -0,0 +1,43 @@ +--- +title: "Running a Sensitive Data Scan" +description: "Executing a sensitive data scan and monitoring progress" +sidebar_position: 40 +--- + +# Running a Sensitive Data Scan + +Sensitive data scans analyze files across your connected data sources to detect content matching your configured detection patterns. Scans are configured and launched through the scan creation wizard. + +## Prerequisites + +Before running a sensitive data scan, ensure the following are in place: + +- At least one data source is connected and accessible +- Detection [patterns](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/builtinpatterns) or [pattern groups](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/patterngroups) are configured +- [Taxonomy groups](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/taxonomygroups) and [classification rules](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/classificationrules) are defined for compliance mapping + +## Launching a Scan + +1. Navigate to the **Scans** section in Access Analyzer. +2. Click **Create Scan** to open the scan creation wizard. +3. Select the target **Data Source(s)** to scan. +4. Under **Scan Options**, enable **Sensitive Data Discovery**. +5. Choose the **Pattern Groups** to apply during the scan. +6. Review the scan configuration summary and click **Start Scan**. + +## Monitoring Progress + +Once a scan is running, you can monitor its status from the **Scans** page. The scan detail view displays: + +- **Progress** — Percentage of files processed +- **Files Scanned** — Count of files analyzed so far +- **Matches Found** — Running total of sensitive data matches + +:::warning +Sensitive data scans are resource-intensive. The `sensitive-data-scan` and `data-classification` serverless functions handle detection workloads. Schedule large scans during off-peak hours to minimize impact on system performance. +::: + +## Next Steps + +- [Review match counts](/docs/accessanalyzer/1_0/sensitivedatadiscovery/reviewingresults/matchcounts) after the scan completes +- [Analyze classification breakdowns](/docs/accessanalyzer/1_0/sensitivedatadiscovery/reviewingresults/classificationbreakdown) by compliance framework diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/_category_.json b/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/_category_.json new file mode 100644 index 0000000000..ce0fe0e2ed --- /dev/null +++ b/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Taxonomy and Classification", + "position": 30, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "taxonomygroups" + } +} diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/autovscustom.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/autovscustom.md new file mode 100644 index 0000000000..0f6c9de35d --- /dev/null +++ b/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/autovscustom.md @@ -0,0 +1,41 @@ +--- +title: "Auto vs Custom Classification" +description: "Automatic and custom classification methods" +sidebar_position: 30 +--- + +# Auto vs Custom Classification + +Netwrix Access Analyzer supports two classification approaches for sensitive data: automatic (built-in) classification and custom classification. You can use either method independently or combine them for comprehensive coverage. + +## Automatic Classification + +Automatic classification uses the built-in patterns and taxonomy groups that ship with Access Analyzer. This approach requires no upfront configuration and covers common sensitive data categories out of the box. + +**Advantages:** + +- Ready to use immediately after installation +- Covers standard compliance frameworks (GDPR, CCPA, HIPAA, PCI DSS, GLBA, CMMC) +- Maintained and updated by Netwrix through the Data Classification SDK + +**Best for:** Organizations that need quick time-to-value and standard regulatory coverage. + +## Custom Classification + +Custom classification uses organization-defined regex patterns, pattern groups, and taxonomy mappings. This approach provides full control over what data is detected and how it is categorized. + +**Advantages:** + +- Detects proprietary or non-standard data formats +- Maps findings to internal policies beyond standard frameworks +- Supports region-specific or industry-specific identifiers + +**Best for:** Organizations with unique data formats or compliance requirements not covered by built-in rules. + +## Combining Both Approaches + +For most deployments, a hybrid approach provides the best coverage. Use automatic classification as a baseline, then layer custom patterns for organization-specific needs. + +:::note +Custom rules take precedence over automatic rules when both match the same data and the custom rule has a higher priority. See [Classification Rules](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/classificationrules) for details on priority settings. +::: diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/classificationrules.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/classificationrules.md new file mode 100644 index 0000000000..028e7e4ed0 --- /dev/null +++ b/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/classificationrules.md @@ -0,0 +1,40 @@ +--- +title: "Classification Rules" +description: "Defining rules that combine patterns and taxonomy" +sidebar_position: 20 +--- + +# Classification Rules + +Classification rules connect detection patterns to taxonomy groups, determining how identified sensitive data is categorized and which compliance frameworks apply to each finding. A rule specifies the conditions under which a pattern match is classified under a particular taxonomy. + +## Rule Components + +Each classification rule consists of: + +| Component | Description | +| --- | --- | +| **Name** | A descriptive label for the rule | +| **Pattern or Pattern Group** | The detection patterns that trigger the rule | +| **Taxonomy Group** | The compliance framework or category the match maps to | +| **Priority** | Determines precedence when multiple rules match the same data | + +## Creating a Classification Rule + +1. Navigate to **Sensitive Data Discovery** > **Taxonomy**. +2. Select the **Classification Rules** tab. +3. Click **Add Rule**. +4. Enter a **Name** for the rule. +5. Select the **Pattern** or **Pattern Group** that triggers this classification. +6. Choose the **Taxonomy Group** the rule maps to (for example, HIPAA, PCI DSS, or a custom group). +7. Set the **Priority** level to control rule precedence. +8. Click **Save**. + +:::note +When a single file matches multiple classification rules, all applicable taxonomy groups are reported. Priority determines which classification is displayed first in summary views. +::: + +## Next Steps + +- [Review built-in versus custom classification](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/autovscustom) to decide which approach fits your needs +- [Run a scan](/docs/accessanalyzer/1_0/sensitivedatadiscovery/runningscan) to apply your classification rules against live data diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/taxonomygroups.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/taxonomygroups.md new file mode 100644 index 0000000000..54e9e01635 --- /dev/null +++ b/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/taxonomygroups.md @@ -0,0 +1,42 @@ +--- +title: "Taxonomy Groups" +description: "Creating and managing data classification categories" +sidebar_position: 10 +--- + +# Taxonomy Groups + +Taxonomy groups map classification rules to compliance frameworks, enabling you to align sensitive data findings with regulatory and organizational requirements. Each taxonomy group represents a compliance standard or internal policy against which scan results are evaluated. + +## Supported Compliance Frameworks + +Access Analyzer includes built-in taxonomy groups for the following frameworks: + +| Framework | Description | +| --- | --- | +| GDPR | General Data Protection Regulation — EU personal data protection | +| CCPA | California Consumer Privacy Act — California resident data rights | +| HIPAA | Health Insurance Portability and Accountability Act — protected health information | +| PCI DSS | Payment Card Industry Data Security Standard — cardholder data protection | +| GLBA | Gramm-Leach-Bliley Act — financial institution consumer data | +| CMMC | Cybersecurity Maturity Model Certification — defense contractor requirements | + +## Managing Taxonomy Groups + +To create or modify a taxonomy group: + +1. Navigate to **Sensitive Data Discovery** > **Taxonomy**. +2. Select the **Taxonomy Groups** tab. +3. Click **Add Group** to create a new group, or select an existing group to edit. +4. Provide a **Name** and select the target **Compliance Framework**. +5. Associate [classification rules](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/classificationrules) that define which data types fall under this group. +6. Click **Save**. + +:::note +Built-in taxonomy groups are pre-mapped to their respective frameworks. You can create additional groups for internal policies or regional regulations not covered by the defaults. +::: + +## Next Steps + +- [Define classification rules](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/classificationrules) to control how data is categorized within each taxonomy group +- [Compare built-in and custom classification](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/autovscustom) approaches diff --git a/docs/accessanalyzer/1.0/troubleshooting/_category_.json b/docs/accessanalyzer/1.0/troubleshooting/_category_.json new file mode 100644 index 0000000000..53df54fda4 --- /dev/null +++ b/docs/accessanalyzer/1.0/troubleshooting/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Monitoring and Troubleshooting", + "position": 100, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "overview" + } +} diff --git a/docs/accessanalyzer/1.0/troubleshooting/commonissues/_category_.json b/docs/accessanalyzer/1.0/troubleshooting/commonissues/_category_.json new file mode 100644 index 0000000000..feba67eef4 --- /dev/null +++ b/docs/accessanalyzer/1.0/troubleshooting/commonissues/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Common Issues", + "position": 40, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "connectionfailures" + } +} diff --git a/docs/accessanalyzer/1.0/troubleshooting/commonissues/connectionfailures.md b/docs/accessanalyzer/1.0/troubleshooting/commonissues/connectionfailures.md new file mode 100644 index 0000000000..f13e0f0872 --- /dev/null +++ b/docs/accessanalyzer/1.0/troubleshooting/commonissues/connectionfailures.md @@ -0,0 +1,61 @@ +--- +title: "Connection Failures" +description: "Diagnosing and resolving connector connection issues" +sidebar_position: 10 +--- + +# Connection Failures + +Access Analyzer connects to external data sources using protocols such as SMB, LDAP, and Microsoft Graph API. Connection failures prevent scans from running and must be resolved before data collection can proceed. + +## Diagnostic Steps + +1. **Check the connector-api pod status:** + +```bash +kubectl get pods -n access-analyzer -l app=connector-api +kubectl logs -n access-analyzer deploy/connector-api --tail=100 +``` + +2. **Verify network connectivity** from the connector pod to the target: + +```bash +kubectl exec -n access-analyzer deploy/connector-api -- curl -v https://: +``` + +3. **Review the source configuration** in the Access Analyzer web UI. Confirm that the hostname, port, and credentials are correct. + +## SMB Connection Failures + +- Verify that TCP port **445** is open between the Access Analyzer cluster and the target file server. +- Confirm that the service account has the required share and NTFS permissions. +- Check for DNS resolution issues by running `nslookup ` from within the connector pod. + +## LDAP Connection Failures + +- Verify that TCP port **389** (LDAP) or **636** (LDAPS) is reachable. +- Confirm that the bind DN and password are correct. +- For LDAPS, ensure the target server's TLS certificate is trusted. Self-signed certificates may require adding a CA bundle. + +## Microsoft Graph API Failures + +- Confirm that the Azure AD application registration has the required API permissions. +- Verify that the client ID, client secret, and tenant ID are correct and that the secret has not expired. +- Check outbound HTTPS connectivity to `https://graph.microsoft.com` and `https://login.microsoftonline.com`. + +```bash +kubectl exec -n access-analyzer deploy/connector-api -- curl -s -o /dev/null -w "%{http_code}" https://graph.microsoft.com/v1.0/ +``` + +## General Troubleshooting + +| Symptom | Likely Cause | Action | +| --- | --- | --- | +| Connection timeout | Firewall or network policy blocking traffic | Verify firewall rules and Kubernetes network policies | +| Authentication error | Invalid or expired credentials | Update credentials in the source configuration | +| TLS handshake failure | Certificate mismatch or expired certificate | Verify TLS certificates on the target service | +| DNS resolution failure | Incorrect hostname or missing DNS entry | Test DNS from within the connector pod | + +:::note +Connection tests run from the `connector-api` pod. Network access from your local machine does not guarantee access from within the cluster. +::: diff --git a/docs/accessanalyzer/1.0/troubleshooting/commonissues/databaseconnectivity.md b/docs/accessanalyzer/1.0/troubleshooting/commonissues/databaseconnectivity.md new file mode 100644 index 0000000000..fb2aebe74c --- /dev/null +++ b/docs/accessanalyzer/1.0/troubleshooting/commonissues/databaseconnectivity.md @@ -0,0 +1,97 @@ +--- +title: "Database Connectivity" +description: "Resolving PostgreSQL, ClickHouse, and Redis connectivity issues" +sidebar_position: 30 +--- + +# Database Connectivity + +Access Analyzer relies on three backing data stores: PostgreSQL for relational data, ClickHouse for analytics and trace storage, and Redis for sessions, caching, and job queues. Connectivity failures to any of these services impact application functionality. + +## Checking Pod Status + +**Verify that all database pods are running:** + +```bash +kubectl get pods -n access-analyzer -l app=postgresql +kubectl get pods -n access-analyzer -l app=clickhouse +kubectl get pods -n access-analyzer -l app=redis +``` + +A pod not in `Running` status requires immediate attention. Use `kubectl describe pod -n access-analyzer` to inspect events and error details. + +## PostgreSQL + +PostgreSQL stores core application data including user accounts, source configurations, and scan results. + +**Test connectivity from the core-api pod:** + +```bash +kubectl exec -n access-analyzer deploy/core-api -- pg_isready -h postgresql -p 5432 +``` + +**Check active connections:** + +```bash +kubectl exec -n access-analyzer deploy/postgresql -- psql -U postgres -c "SELECT count(*) FROM pg_stat_activity;" +``` + +Common issues: +- **Too many connections** -- The connection pool is exhausted. Restart the application pods or increase the pool size. +- **Pod in CrashLoopBackOff** -- Check PostgreSQL logs for disk space or corruption errors. + +## ClickHouse + +ClickHouse stores analytics data and OpenTelemetry traces in the `access_analyzer_logs` database. + +**Test connectivity:** + +```bash +kubectl exec -n access-analyzer deploy/clickhouse -- clickhouse-client --query "SELECT 1" +``` + +**Check database availability:** + +```bash +kubectl exec -n access-analyzer deploy/clickhouse -- clickhouse-client --query "SHOW DATABASES" +``` + +Common issues: +- **Disk pressure** -- ClickHouse can consume significant storage for trace and analytics data. Monitor disk usage with `kubectl exec -n access-analyzer deploy/clickhouse -- df -h`. +- **Query timeout** -- Large analytical queries can time out. Check ClickHouse server logs for slow query warnings. + +## Redis + +Redis provides session storage, caching, and serves as the job queue backend for Sidekiq. + +**Test connectivity:** + +```bash +kubectl exec -n access-analyzer deploy/redis -- redis-cli ping +``` + +A successful response returns `PONG`. + +**Check memory usage:** + +```bash +kubectl exec -n access-analyzer deploy/redis -- redis-cli info memory | grep used_memory_human +``` + +Common issues: +- **MaxMemory reached** -- Redis evicts keys or rejects writes when memory is full. Increase the memory limit or review eviction policies. +- **Connection refused** -- The Redis pod may have restarted. Check pod status and events. + +## Deep Health Check + +Use the application health endpoint to validate connectivity to all backing services at once: + +```bash +kubectl exec -n access-analyzer deploy/core-api -- curl -s http://localhost:3000/api/v1/monitoring/__health +``` + +This endpoint reports the status of each backing service and identifies which connection is failing. See [Service Health Endpoints](/docs/accessanalyzer/1.0/troubleshooting/healthchecks/endpoints) for more details. + +:::warning +Database connectivity failures cascade across the application. If multiple services report errors simultaneously, start by verifying database pod health before troubleshooting individual application pods. +::: diff --git a/docs/accessanalyzer/1.0/troubleshooting/commonissues/scanerrors.md b/docs/accessanalyzer/1.0/troubleshooting/commonissues/scanerrors.md new file mode 100644 index 0000000000..4bd3cf333c --- /dev/null +++ b/docs/accessanalyzer/1.0/troubleshooting/commonissues/scanerrors.md @@ -0,0 +1,61 @@ +--- +title: "Scan Errors" +description: "Common scan execution errors and solutions" +sidebar_position: 20 +--- + +# Scan Errors + +Scan errors occur when Access Analyzer encounters problems during data collection from configured sources. This page covers common scan errors, their causes, and resolution steps. + +## Checking Scan Status + +Review scan status in the Access Analyzer web UI or check the logs from the relevant pods: + +```bash +kubectl logs -n access-analyzer deploy/core-api --tail=200 | grep -i scan +kubectl logs -n access-analyzer deploy/connector-api --tail=200 | grep -i scan +``` + +## Common Scan Errors + +### Scan Timeout + +Scans that exceed the configured timeout are terminated automatically. + +- **Cause**: Large data sources, slow network connectivity, or insufficient worker resources. +- **Resolution**: Increase the scan timeout if appropriate, reduce the scan scope, or allocate additional resources to worker pods. + +### Pod Failures During Scan + +If the pod executing a scan is killed or restarted mid-scan, the scan fails without completing. + +```bash +kubectl get pods -n access-analyzer --field-selector=status.phase=Failed +kubectl describe pod -n access-analyzer +``` + +- **Cause**: OOMKilled (out of memory), node eviction, or liveness probe timeout. +- **Resolution**: Check pod events for `OOMKilled` status. Increase memory limits for the affected pod if needed. Review node resource pressure with `kubectl top nodes`. + +### Permission Denied Errors + +The scan account lacks the required permissions on the target data source. + +- **Cause**: Insufficient privileges for the configured service account. +- **Resolution**: Verify that the service account has the permissions documented for the source type. See [Connection Failures](/docs/accessanalyzer/1.0/troubleshooting/commonissues/connectionfailures) for protocol-specific requirements. + +### Partial Scan Results + +A scan completes but returns fewer results than expected. + +- **Cause**: Access denied on a subset of resources, or rate limiting by the target API. +- **Resolution**: Review the scan logs for warnings about skipped resources. For API-based sources, check for throttling responses (HTTP 429). + +## Reviewing Scan Job History + +Failed scan jobs appear in the Sidekiq **Retries** or **Dead** tab. See [Failed Job Troubleshooting](/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/failedjobs) for instructions on inspecting and retrying failed jobs. + +:::warning +If scans fail consistently across multiple sources, check cluster-wide resource availability and backing service health before investigating individual source configurations. +::: diff --git a/docs/accessanalyzer/1.0/troubleshooting/healthchecks/_category_.json b/docs/accessanalyzer/1.0/troubleshooting/healthchecks/_category_.json new file mode 100644 index 0000000000..affcb1f52d --- /dev/null +++ b/docs/accessanalyzer/1.0/troubleshooting/healthchecks/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Health Checks", + "position": 10, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "probes" + } +} diff --git a/docs/accessanalyzer/1.0/troubleshooting/healthchecks/endpoints.md b/docs/accessanalyzer/1.0/troubleshooting/healthchecks/endpoints.md new file mode 100644 index 0000000000..772ef5edf7 --- /dev/null +++ b/docs/accessanalyzer/1.0/troubleshooting/healthchecks/endpoints.md @@ -0,0 +1,49 @@ +--- +title: "Service Health Endpoints" +description: "Service-specific health check URLs" +sidebar_position: 20 +--- + +# Service Health Endpoints + +Access Analyzer exposes several HTTP health check endpoints that report on service availability. Use these endpoints to verify that application services are running and responsive. + +## Available Endpoints + +| Endpoint | Purpose | Expected Response | +| --- | --- | --- | +| `/health/live` | Liveness check. Confirms the process is running. | `200 OK` | +| `/health/ready` | Readiness check. Confirms the service can handle requests. | `200 OK` | +| `/api/v1/monitoring/__health` | Deep health check. Validates connectivity to backing services (database, cache). | `200 OK` with JSON status | + +## Querying Health Endpoints + +**From within the cluster, use `kubectl exec` to curl a health endpoint:** + +```bash +kubectl exec -n access-analyzer deploy/core-api -- curl -s http://localhost:3000/health/live +``` + +**Check the readiness endpoint:** + +```bash +kubectl exec -n access-analyzer deploy/core-api -- curl -s http://localhost:3000/health/ready +``` + +**Run the deep health check to verify backing service connectivity:** + +```bash +kubectl exec -n access-analyzer deploy/core-api -- curl -s http://localhost:3000/api/v1/monitoring/__health +``` + +The deep health check at `/api/v1/monitoring/__health` validates that the application can reach PostgreSQL, ClickHouse, and Redis. A failure response from this endpoint identifies which backing service is unreachable. + +## Interpreting Results + +- A `200 OK` response indicates the service is healthy. +- A non-200 response or connection timeout indicates a problem. Check the pod logs for additional context. +- If `/health/live` passes but `/health/ready` fails, the service is running but cannot process requests, typically due to a dependency being unavailable. + +:::note +The `/api/v1/monitoring/__health` endpoint performs active checks against all backing services. Use it for thorough health verification, but avoid calling it at high frequency as it places load on downstream systems. +::: diff --git a/docs/accessanalyzer/1.0/troubleshooting/healthchecks/probes.md b/docs/accessanalyzer/1.0/troubleshooting/healthchecks/probes.md new file mode 100644 index 0000000000..8f2b0697b8 --- /dev/null +++ b/docs/accessanalyzer/1.0/troubleshooting/healthchecks/probes.md @@ -0,0 +1,55 @@ +--- +title: "Liveness and Readiness Probes" +description: "Kubernetes health probe endpoints" +sidebar_position: 10 +--- + +# Liveness and Readiness Probes + +Kubernetes uses liveness and readiness probes to monitor the health of pods in the Access Analyzer deployment. Understanding these probes helps you diagnose pod restarts and service availability issues. + +## How Probes Work + +- **Liveness probes** determine whether a container is running. If a liveness probe fails, Kubernetes restarts the container. +- **Readiness probes** determine whether a container is ready to accept traffic. If a readiness probe fails, Kubernetes removes the pod from service endpoints until it passes again. + +## Checking Probe Status + +**View the current state of all pods in the Access Analyzer namespace:** + +```bash +kubectl get pods -n access-analyzer +``` + +A pod in `CrashLoopBackOff` status typically indicates repeated liveness probe failures. A pod showing `0/1 Ready` may be failing its readiness probe. + +**Inspect probe configuration and recent events for a specific pod:** + +```bash +kubectl describe pod -n access-analyzer +``` + +Look for the `Liveness` and `Readiness` fields in the output to see the probe endpoint, interval, timeout, and failure threshold. The **Events** section at the bottom shows recent probe failures and container restarts. + +**View logs from a pod that is restarting:** + +```bash +kubectl logs -n access-analyzer --previous +``` + +The `--previous` flag retrieves logs from the last terminated container, which is useful when a pod has already restarted. + +## Key Pods to Monitor + +| Pod | Purpose | +| --- | --- | +| `core-api` | Primary API server | +| `webapp` | Web application frontend | +| `connector-api` | Source connector service | +| `postgresql` | Relational data store | +| `clickhouse` | Analytics data store | +| `redis` | Session and cache store | + +:::warning +Frequent pod restarts caused by probe failures often indicate resource pressure (memory or CPU) rather than application bugs. Check node resource utilization with `kubectl top nodes` before investigating application-level issues. +::: diff --git a/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/_category_.json b/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/_category_.json new file mode 100644 index 0000000000..53ae508120 --- /dev/null +++ b/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Background Job Monitoring", + "position": 30, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "sidekiq" + } +} diff --git a/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/failedjobs.md b/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/failedjobs.md new file mode 100644 index 0000000000..b6749b9aa9 --- /dev/null +++ b/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/failedjobs.md @@ -0,0 +1,58 @@ +--- +title: "Failed Job Troubleshooting" +description: "Diagnosing and resolving failed background jobs" +sidebar_position: 30 +--- + +# Failed Job Troubleshooting + +When a Sidekiq background job encounters an error, it enters the retry cycle. Jobs that exhaust all retry attempts move to the dead set. This page explains how to find, diagnose, and resolve failed jobs. + +## Finding Failed Jobs + +Open the [Sidekiq Dashboard](/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/sidekiq) and navigate to the following tabs: + +- **Retries** -- Jobs that failed and are awaiting automatic retry. Each entry displays the error class, error message, and the number of retries attempted. +- **Dead** -- Jobs that exhausted all retry attempts. Dead jobs are not retried automatically and require manual action. + +## Retry Behavior + +Sidekiq uses an exponential backoff strategy for retries. The delay between retries increases with each attempt, following the formula: + +``` +(retry_count ^ 4) + 15 + (random(10) * (retry_count + 1)) seconds +``` + +By default, a job retries up to 25 times before being moved to the dead set. This means a failing job may continue retrying for approximately 21 days before it is considered dead. + +## Diagnosing Failures + +1. **Check the error message** in the Retries or Dead tab. The error class and message typically indicate the root cause (for example, a connection timeout or validation error). +2. **Review application logs** for the time of the failure: + +```bash +kubectl logs -n access-analyzer deploy/core-api --since=1h | grep -i error +``` + +3. **Check backing service health** -- Many job failures stem from database or Redis connectivity issues. See [Database Connectivity](/docs/accessanalyzer/1.0/troubleshooting/commonissues/databaseconnectivity). + +## Handling Dead Jobs + +From the **Dead** tab in the Sidekiq dashboard, you can: + +- **Retry** a specific dead job to re-enqueue it for processing. +- **Delete** a dead job to remove it permanently. +- **Retry All** to re-enqueue all dead jobs at once. + +:::warning +Before retrying dead jobs, ensure the underlying issue has been resolved. Retrying jobs without fixing the root cause will result in repeated failures. +::: + +## Common Failure Causes + +| Cause | Symptoms | Resolution | +| --- | --- | --- | +| Redis unavailable | All jobs fail simultaneously | Verify Redis pod health | +| Database timeout | Jobs in `scans` or `syncs` queues fail | Check PostgreSQL/ClickHouse connectivity | +| External API error | Connector-related jobs fail | Verify source credentials and network access | +| Memory pressure | Jobs killed mid-execution | Increase worker pod memory limits | diff --git a/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/queues.md b/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/queues.md new file mode 100644 index 0000000000..3dc007d084 --- /dev/null +++ b/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/queues.md @@ -0,0 +1,52 @@ +--- +title: "Job Queues and Priorities" +description: "Understanding job queue structure and priority levels" +sidebar_position: 20 +--- + +# Job Queues and Priorities + +Access Analyzer processes background work through seven Sidekiq queues, each serving a specific purpose. Understanding queue roles and priorities helps you identify processing bottlenecks and backpressure. + +## Queue Overview + +| Queue | Priority | Purpose | +| --- | --- | --- | +| `critical` | Highest | System-critical operations that must complete promptly | +| `scans` | High | Data source scan execution | +| `syncs` | High | Data synchronization between sources and the platform | +| `scheduler` | Medium | Periodic task scheduling and orchestration | +| `default` | Medium | General-purpose background work | +| `mailers` | Low | Email notification delivery | +| `low` | Lowest | Deferred or non-urgent tasks | + +Sidekiq workers process queues in priority order. Higher-priority queues are drained before lower-priority ones. + +## Monitoring Queue Depth + +**From the Sidekiq dashboard**, navigate to the **Queues** tab to view the current size of each queue. A queue size that grows continuously indicates that jobs are being enqueued faster than workers can process them. + +**From the command line, query Prometheus for queue sizes:** + +```bash +kubectl exec -n access-analyzer deploy/prometheus -- \ + promtool query instant http://localhost:9090 'sidekiq_queue_size' +``` + +## Identifying Backpressure + +Backpressure occurs when one or more queues accumulate jobs faster than they are processed. Common causes include: + +- **Resource constraints** -- Insufficient CPU or memory on worker pods. Check with `kubectl top pods -n access-analyzer`. +- **Downstream dependency failures** -- Database or external service unavailability causing job retries and requeuing. +- **Large scan jobs** -- A scan targeting a large data source can consume worker capacity, delaying other queues. + +:::warning +If the `critical` queue has a sustained non-zero depth, investigate immediately. Delayed critical jobs can affect system stability and data consistency. +::: + +## Corrective Actions + +- Scale worker replicas if resource limits allow. +- Investigate and resolve downstream dependency failures (see [Database Connectivity](/docs/accessanalyzer/1.0/troubleshooting/commonissues/databaseconnectivity)). +- Stagger large scan jobs to avoid overwhelming worker capacity. diff --git a/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/sidekiq.md b/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/sidekiq.md new file mode 100644 index 0000000000..a7b43638c9 --- /dev/null +++ b/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/sidekiq.md @@ -0,0 +1,50 @@ +--- +title: "Sidekiq Dashboard" +description: "Monitoring background jobs via the Sidekiq web UI" +sidebar_position: 10 +--- + +# Sidekiq Dashboard + +Access Analyzer uses Sidekiq to process background jobs such as scans, syncs, and scheduled tasks. The Sidekiq web dashboard provides real-time visibility into job processing, queue health, and worker status. + +## Accessing the Dashboard + +The Sidekiq dashboard is available at the `/sidekiq` path on your Access Analyzer instance: + +``` +https:///sidekiq +``` + +The dashboard requires authentication. Enter the configured username and password when prompted. + +:::note +Dashboard credentials are set during installation. Contact your system administrator if you do not have the credentials. +::: + +## Dashboard Capabilities + +The Sidekiq web UI provides the following views: + +- **Dashboard** -- Real-time graph of processed and failed jobs over time. +- **Busy** -- Lists workers currently executing jobs, including the job class and arguments. +- **Queues** -- Displays all queues with their current size. Use this to identify backpressure. +- **Retries** -- Shows jobs that failed and are scheduled for automatic retry. +- **Scheduled** -- Lists jobs enqueued for future execution. +- **Dead** -- Contains jobs that exhausted all retry attempts. These require manual intervention. + +## Checking Job Throughput + +From the dashboard home page, review the **Processed** and **Failed** counters. A healthy system shows a steadily increasing processed count with a low or zero failed count. + +If the failed count is climbing, navigate to the **Retries** tab to inspect the error messages and determine the root cause. + +## Infrastructure Dependency + +Sidekiq depends on Redis for job storage and queue management. If the Sidekiq dashboard is unreachable or shows no data, verify that the Redis pod is running: + +```bash +kubectl get pods -n access-analyzer -l app=redis +``` + +See [Job Queues and Priorities](/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/queues) for details on individual queue behavior. diff --git a/docs/accessanalyzer/1.0/troubleshooting/observability/_category_.json b/docs/accessanalyzer/1.0/troubleshooting/observability/_category_.json new file mode 100644 index 0000000000..d6e5ecaf0a --- /dev/null +++ b/docs/accessanalyzer/1.0/troubleshooting/observability/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Observability", + "position": 20, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "opentelemetry" + } +} diff --git a/docs/accessanalyzer/1.0/troubleshooting/observability/opentelemetry.md b/docs/accessanalyzer/1.0/troubleshooting/observability/opentelemetry.md new file mode 100644 index 0000000000..d9d1ec28e6 --- /dev/null +++ b/docs/accessanalyzer/1.0/troubleshooting/observability/opentelemetry.md @@ -0,0 +1,76 @@ +--- +title: "OpenTelemetry Traces and Metrics" +description: "Distributed tracing and metric collection" +sidebar_position: 10 +--- + +# OpenTelemetry Traces and Metrics + +Access Analyzer uses OpenTelemetry (OTel) for distributed tracing. Traces are collected by the `otel-collector` pod and stored in ClickHouse, allowing you to analyze request flows and identify performance bottlenecks. + +## Architecture + +Trace data flows through the following path: + +1. Application services instrument outgoing requests and operations with OTel spans. +2. The `otel-collector` pod receives spans and exports them to ClickHouse. +3. Traces are stored in the `access_analyzer_logs` database in ClickHouse. + +## Querying Traces in ClickHouse + +**Connect to the ClickHouse pod:** + +```bash +kubectl exec -it -n access-analyzer deploy/clickhouse -- clickhouse-client +``` + +**List available tables in the trace database:** + +```bash +USE access_analyzer_logs; +SHOW TABLES; +``` + +**Query recent traces by service name:** + +```bash +SELECT TraceId, SpanName, Duration, StatusCode +FROM otel_traces +WHERE ServiceName = 'core-api' +ORDER BY Timestamp DESC +LIMIT 20; +``` + +**Find slow spans exceeding a duration threshold (in nanoseconds):** + +```bash +SELECT TraceId, SpanName, Duration +FROM otel_traces +WHERE Duration > 5000000000 +ORDER BY Duration DESC +LIMIT 10; +``` + +## Common Trace Analysis + +- **High latency requests** -- Query for spans with long durations to identify slow database queries or external API calls. +- **Error spans** -- Filter by `StatusCode` to find spans that completed with errors. +- **Cross-service tracing** -- Use a `TraceId` to follow a request across `core-api`, `connector-api`, and backing services. + +## Verifying the OTel Collector + +**Check that the collector pod is running:** + +```bash +kubectl get pods -n access-analyzer -l app=otel-collector +``` + +**View collector logs for export errors:** + +```bash +kubectl logs -n access-analyzer deploy/otel-collector --tail=50 +``` + +:::note +Trace retention depends on your ClickHouse storage configuration. Monitor disk usage on the ClickHouse pod to ensure traces are not consuming excessive storage. +::: diff --git a/docs/accessanalyzer/1.0/troubleshooting/observability/prometheus.md b/docs/accessanalyzer/1.0/troubleshooting/observability/prometheus.md new file mode 100644 index 0000000000..253f2f8b3a --- /dev/null +++ b/docs/accessanalyzer/1.0/troubleshooting/observability/prometheus.md @@ -0,0 +1,70 @@ +--- +title: "Prometheus Monitoring" +description: "Prometheus metrics and alerting" +sidebar_position: 20 +--- + +# Prometheus Monitoring + +Access Analyzer includes a Prometheus instance that collects metrics from application services and infrastructure components. Use Prometheus to monitor resource utilization, request rates, and application performance. + +## Accessing Prometheus + +The Prometheus pod runs in the `access-analyzer` namespace. To access the Prometheus web UI, set up a port forward: + +```bash +kubectl port-forward -n access-analyzer deploy/prometheus 9090:9090 +``` + +Then open `http://localhost:9090` in your browser. + +## Key Metrics to Monitor + +| Metric | Description | +| --- | --- | +| `container_memory_usage_bytes` | Memory consumption per container | +| `container_cpu_usage_seconds_total` | CPU usage per container | +| `http_request_duration_seconds` | Request latency histogram | +| `http_requests_total` | Total request count by status code | +| `sidekiq_queue_size` | Number of jobs waiting in each Sidekiq queue | +| `pg_stat_activity_count` | Active PostgreSQL connections | + +## Useful PromQL Queries + +**Check memory usage for Access Analyzer pods:** + +```bash +container_memory_usage_bytes{namespace="access-analyzer"} +``` + +**Calculate request error rate over the last 5 minutes:** + +```bash +rate(http_requests_total{namespace="access-analyzer", status=~"5.."}[5m]) +``` + +**Monitor Sidekiq queue depth:** + +```bash +sidekiq_queue_size{namespace="access-analyzer"} +``` + +## Recording Rules + +Access Analyzer ships with Prometheus recording rules that pre-compute frequently used metric aggregations. Recording rules reduce query latency for dashboards and alerts. View the active recording rules in the Prometheus UI under **Status > Rules**. + +## Verifying Prometheus Health + +**Confirm the Prometheus pod is running:** + +```bash +kubectl get pods -n access-analyzer -l app=prometheus +``` + +**Check Prometheus targets to ensure all scrape endpoints are reachable:** + +Open `http://localhost:9090/targets` (with port forward active) and verify all targets show an **UP** state. + +:::warning +If Prometheus targets appear as **DOWN**, verify that the target pods are running and that network policies allow traffic from the Prometheus pod on the metrics port. +::: diff --git a/docs/accessanalyzer/1.0/troubleshooting/overview.md b/docs/accessanalyzer/1.0/troubleshooting/overview.md new file mode 100644 index 0000000000..806ed1a446 --- /dev/null +++ b/docs/accessanalyzer/1.0/troubleshooting/overview.md @@ -0,0 +1,70 @@ +--- +title: "Monitoring and Troubleshooting" +description: "Health checks, observability, and common issue resolution" +sidebar_position: 1 +--- + +# Monitoring and Troubleshooting + +This section provides guidance for monitoring the health of your Netwrix Access Analyzer deployment and resolving common issues. Use the categories below to navigate to the relevant topic. + +## Troubleshooting Categories + +| Category | Description | Link | +| --- | --- | --- | +| Health Checks | Kubernetes probes and service health endpoints | [Probes](/docs/accessanalyzer/1.0/troubleshooting/healthchecks/probes), [Endpoints](/docs/accessanalyzer/1.0/troubleshooting/healthchecks/endpoints) | +| Observability | Distributed tracing and metrics collection | [OpenTelemetry](/docs/accessanalyzer/1.0/troubleshooting/observability/opentelemetry), [Prometheus](/docs/accessanalyzer/1.0/troubleshooting/observability/prometheus) | +| Job Monitoring | Background job processing and queue health | [Sidekiq](/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/sidekiq), [Queues](/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/queues), [Failed Jobs](/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/failedjobs) | +| Common Issues | Connection failures, scan errors, and database connectivity | [Connections](/docs/accessanalyzer/1.0/troubleshooting/commonissues/connectionfailures), [Scans](/docs/accessanalyzer/1.0/troubleshooting/commonissues/scanerrors), [Database](/docs/accessanalyzer/1.0/troubleshooting/commonissues/databaseconnectivity) | + +## Quick Diagnostic Commands + +Run the following commands to get an immediate overview of system health. + +**Check all pod status across namespaces:** + +```bash +kubectl get pods -A +``` + +**View resource consumption for nodes and pods:** + +```bash +kubectl top nodes +kubectl top pods -n access-analyzer +``` + +**Check ArgoCD application sync status:** + +```bash +kubectl get apps -n argocd +``` + +**View logs for a specific pod:** + +```bash +kubectl logs -n access-analyzer --tail=100 +``` + +**Review installer and preflight logs:** + +```bash +cat /var/log/dspm-installer.log +cat /var/log/dspm-preflight.json +``` + +## Installer Exit Codes + +If installation failed, check the exit code to identify the failure category. + +| Exit Code | Meaning | +| --- | --- | +| 10 | License validation failure | +| 50 | K3s installation or startup failure | +| 60 | ArgoCD deployment failure | +| 70 | Application readiness timeout | +| 80 | Preflight check failure (CPU, memory, disk, kernel, or cgroups) | + +:::note +Most troubleshooting commands require `kubectl` access to the cluster. Ensure your kubeconfig is configured correctly before running diagnostics. +::: diff --git a/kb_allowlist.json b/kb_allowlist.json index da0e08b082..b39f8edc6e 100644 --- a/kb_allowlist.json +++ b/kb_allowlist.json @@ -3,6 +3,7 @@ "current" ], "accessanalyzer": [ + "1.0", "11.6", "12.0" ], diff --git a/sidebars/accessanalyzer/1.0.js b/sidebars/accessanalyzer/1.0.js new file mode 100644 index 0000000000..f4e8941a40 --- /dev/null +++ b/sidebars/accessanalyzer/1.0.js @@ -0,0 +1,8 @@ +module.exports = { + sidebar: [ + { + type: 'autogenerated', + dirName: '.', + }, + ], +}; diff --git a/src/config/products.js b/src/config/products.js index 76a1e35884..a1e65be057 100644 --- a/src/config/products.js +++ b/src/config/products.js @@ -60,6 +60,12 @@ export const PRODUCTS = [ categories: ['Data Security Posture Management (DSPM)', 'Identity Threat Detection & Response (ITDR)'], icon: '', versions: [ + { + version: '1.0', + label: '1.0', + isLatest: false, + sidebarFile: './sidebars/accessanalyzer/1.0.js', + }, { version: '12.0', label: '12.0', From f2f72d5f30e97d5e2546692e803c1e189b2b57fb Mon Sep 17 00:00:00 2001 From: carlos-mejia_nwx Date: Thu, 19 Mar 2026 21:36:21 -0400 Subject: [PATCH 14/62] =?UTF-8?q?AA26:=20Restructure=20outline=20=E2=80=94?= =?UTF-8?q?=20Overview=20+=20KB=20only,=20on-prem=20verbiage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Move requirements/ and install/ under overview/ as subsections - Rename overview intro to "Intro to the Product" - Delete architecture.md (not needed) - Remove 7 top-level sections: getting started, connectors, admin, dashboards, sensitive data discovery, activity monitoring, troubleshooting - Clear KB articles, keep as placeholder - Update all verbiage to reflect on-premises deployment (not cloud/SaaS) Co-Authored-By: Claude Opus 4.6 --- .../1.0/activitymonitoring/_category_.json | 10 -- .../configuration/_category_.json | 10 -- .../configuration/batchprocessing.md | 8 -- .../configuration/connectingnam.md | 8 -- .../configuration/enablingsyslog.md | 8 -- .../1.0/activitymonitoring/overview.md | 8 -- .../viewingdata/_category_.json | 10 -- .../viewingdata/fileaccessevents.md | 8 -- .../viewingdata/useractivitypatterns.md | 8 -- docs/accessanalyzer/1.0/admin/_category_.json | 10 -- .../1.0/admin/auditlogs/_category_.json | 10 -- .../1.0/admin/auditlogs/export.md | 43 -------- .../1.0/admin/auditlogs/overview.md | 39 -------- .../1.0/admin/authentication/_category_.json | 10 -- .../1.0/admin/authentication/overview.md | 34 ------- .../admin/authentication/sessionmonitoring.md | 38 -------- .../1.0/admin/authentication/tokenrefresh.md | 34 ------- .../1.0/admin/iam/_category_.json | 10 -- .../1.0/admin/iam/identitiesentitlements.md | 36 ------- .../1.0/admin/iam/identitysync.md | 43 -------- docs/accessanalyzer/1.0/admin/iam/overview.md | 32 ------ .../1.0/admin/iam/permissionpaths.md | 39 -------- .../1.0/admin/navigate/_category_.json | 10 -- .../1.0/admin/navigate/datatables.md | 35 ------- .../1.0/admin/navigate/overview.md | 27 ------ .../1.0/admin/navigate/sidebar.md | 34 ------- docs/accessanalyzer/1.0/admin/overview.md | 29 ------ .../1.0/admin/scans/_category_.json | 10 -- .../1.0/admin/scans/executionhistory.md | 44 --------- .../1.0/admin/scans/overview.md | 31 ------ .../1.0/admin/scans/runningstop.md | 42 -------- .../1.0/admin/scans/scantypes.md | 64 ------------ .../1.0/admin/scans/scheduling.md | 50 ---------- .../1.0/admin/sensitivedata/_category_.json | 10 -- .../sensitivedata/customclassification.md | 44 --------- .../1.0/admin/sensitivedata/overview.md | 34 ------- .../1.0/admin/sensitivedata/patterngroups.md | 43 -------- .../1.0/admin/sensitivedata/taxonomygroups.md | 39 -------- .../1.0/admin/serviceaccounts/_category_.json | 10 -- .../1.0/admin/serviceaccounts/associating.md | 42 -------- .../admin/serviceaccounts/credentialtypes.md | 37 ------- .../1.0/admin/serviceaccounts/overview.md | 33 ------- .../1.0/admin/settings/_category_.json | 10 -- .../1.0/admin/settings/featureflags.md | 48 --------- .../1.0/admin/settings/overview.md | 33 ------- .../1.0/admin/settings/scanlimits.md | 37 ------- .../1.0/admin/settings/sessionttl.md | 41 -------- .../1.0/admin/sources/_category_.json | 10 -- .../1.0/admin/sources/editdelete.md | 40 -------- .../1.0/admin/sources/overview.md | 42 -------- .../1.0/admin/sources/sourcegroups.md | 51 ---------- .../1.0/admin/sources/sourcetypes.md | 35 ------- .../1.0/admin/sources/testconnections.md | 54 ----------- docs/accessanalyzer/1.0/admin/systemlogs.md | 47 --------- .../1.0/admin/users/_category_.json | 10 -- .../1.0/admin/users/overview.md | 38 -------- docs/accessanalyzer/1.0/admin/users/roles.md | 36 ------- .../1.0/admin/users/sessions.md | 35 ------- .../1.0/connectors/_category_.json | 10 -- .../1.0/connectors/iam/_category_.json | 10 -- .../iam/activedirectory/_category_.json | 10 -- .../iam/activedirectory/connectionsetup.md | 47 --------- .../iam/activedirectory/customattributes.md | 12 --- .../iam/activedirectory/groupmembership.md | 26 ----- .../iam/activedirectory/usergroupsync.md | 30 ------ .../connectors/iam/entraid/_category_.json | 10 -- .../connectors/iam/entraid/appregistration.md | 74 -------------- .../connectors/iam/entraid/certificateauth.md | 12 --- .../connectors/iam/entraid/usergroupsync.md | 47 --------- .../iam/localgroups/_category_.json | 10 -- .../iam/localgroups/powershellsetup.md | 52 ---------- .../iam/localgroups/usergroupcollection.md | 40 -------- .../1.0/connectors/iam/overview.md | 21 ---- .../accessanalyzer/1.0/connectors/overview.md | 42 -------- .../1.0/connectors/source/_category_.json | 10 -- .../connectors/source/cifs/_category_.json | 10 -- .../source/cifs/connectionconfig.md | 79 --------------- .../source/cifs/filevssharelevel.md | 53 ---------- .../connectors/source/cifs/ntfspermissions.md | 33 ------- .../source/cifs/scandepthworkers.md | 54 ----------- .../source/cifs/shareenumeration.md | 53 ---------- .../1.0/connectors/source/overview.md | 23 ----- .../source/sharepointonline/_category_.json | 10 -- .../sharepointonline/connectionconfig.md | 44 --------- .../permissionsharinglinks.md | 35 ------- .../sharepointonline/scanningspecificsites.md | 30 ------ .../sharepointonline/sitelibraryenum.md | 29 ------ .../1.0/dashboards/_category_.json | 10 -- .../1.0/dashboards/activedirectory.md | 8 -- .../1.0/dashboards/copilotreadiness.md | 8 -- .../1.0/dashboards/datasecurity.md | 8 -- docs/accessanalyzer/1.0/dashboards/entraid.md | 8 -- .../1.0/dashboards/metabase/_category_.json | 10 -- .../dashboards/metabase/accessingreports.md | 36 ------- .../1.0/dashboards/metabase/exportingdata.md | 41 -------- .../1.0/dashboards/metabase/savedreports.md | 38 -------- .../accessanalyzer/1.0/dashboards/overview.md | 33 ------- .../1.0/gettingstarted/_category_.json | 10 -- .../gettingstarted/dashboardwalkthrough.md | 44 --------- .../1.0/gettingstarted/firstlogin.md | 52 ---------- .../gettingstarted/firstscan/_category_.json | 10 -- .../gettingstarted/firstscan/addingsource.md | 70 ------------- .../firstscan/configuringscan.md | 94 ------------------ .../1.0/gettingstarted/firstscan/overview.md | 28 ------ .../gettingstarted/firstscan/runningscan.md | 56 ----------- .../firstscan/viewingresults.md | 49 ---------- .../1.0/gettingstarted/overview.md | 26 ----- docs/accessanalyzer/1.0/index.md | 18 +--- .../1.0/overview/architecture.md | 69 ------------- .../{ => overview}/install/_category_.json | 0 .../1.0/{ => overview}/install/dspmctl.md | 0 .../install/environmentvariables.md | 0 .../1.0/{ => overview}/install/network.md | 0 .../1.0/{ => overview}/install/overview.md | 0 .../1.0/{ => overview}/install/postinstall.md | 0 .../1.0/{ => overview}/install/preflight.md | 0 .../{ => overview}/install/quickinstall.md | 0 .../{ => overview}/install/requirements.md | 0 .../1.0/{ => overview}/install/security.md | 0 .../1.0/{ => overview}/install/ssl.md | 0 .../1.0/{ => overview}/install/stepbystep.md | 0 .../1.0/{ => overview}/install/uninstall.md | 0 .../1.0/{ => overview}/install/upgrade.md | 0 .../1.0/overview/keyconcepts.md | 4 +- docs/accessanalyzer/1.0/overview/overview.md | 18 ++-- .../requirements/_category_.json | 0 .../requirements/connectors/_category_.json | 0 .../connectors/activedirectory.md | 0 .../requirements/connectors/cifs.md | 0 .../requirements/connectors/entraid.md | 0 .../requirements/connectors/localgroups.md | 0 .../connectors/sharepointonline.md | 0 .../requirements/database/_category_.json | 0 .../requirements/database/clickhouse.md | 0 .../requirements/database/postgresql.md | 0 .../requirements/database/redis.md | 0 .../{ => overview}/requirements/overview.md | 0 .../requirements/system/_category_.json | 0 .../requirements/system/hardware.md | 0 .../requirements/system/kubernetes.md | 0 .../requirements/system/network.md | 0 .../sensitivedatadiscovery/_category_.json | 10 -- .../1.0/sensitivedatadiscovery/overview.md | 32 ------ .../patterns/_category_.json | 10 -- .../patterns/builtinpatterns.md | 34 ------- .../patterns/custompatterns.md | 47 --------- .../patterns/patterngroups.md | 39 -------- .../reviewingresults/_category_.json | 10 -- .../classificationbreakdown.md | 43 -------- .../reviewingresults/matchcounts.md | 46 --------- .../1.0/sensitivedatadiscovery/runningscan.md | 43 -------- .../taxonomy/_category_.json | 10 -- .../taxonomy/autovscustom.md | 41 -------- .../taxonomy/classificationrules.md | 40 -------- .../taxonomy/taxonomygroups.md | 42 -------- .../1.0/troubleshooting/_category_.json | 10 -- .../commonissues/_category_.json | 10 -- .../commonissues/connectionfailures.md | 61 ------------ .../commonissues/databaseconnectivity.md | 97 ------------------- .../commonissues/scanerrors.md | 61 ------------ .../healthchecks/_category_.json | 10 -- .../troubleshooting/healthchecks/endpoints.md | 49 ---------- .../troubleshooting/healthchecks/probes.md | 55 ----------- .../jobmonitoring/_category_.json | 10 -- .../jobmonitoring/failedjobs.md | 58 ----------- .../troubleshooting/jobmonitoring/queues.md | 52 ---------- .../troubleshooting/jobmonitoring/sidekiq.md | 50 ---------- .../observability/_category_.json | 10 -- .../observability/opentelemetry.md | 76 --------------- .../observability/prometheus.md | 70 ------------- .../1.0/troubleshooting/overview.md | 70 ------------- 171 files changed, 15 insertions(+), 4536 deletions(-) delete mode 100644 docs/accessanalyzer/1.0/activitymonitoring/_category_.json delete mode 100644 docs/accessanalyzer/1.0/activitymonitoring/configuration/_category_.json delete mode 100644 docs/accessanalyzer/1.0/activitymonitoring/configuration/batchprocessing.md delete mode 100644 docs/accessanalyzer/1.0/activitymonitoring/configuration/connectingnam.md delete mode 100644 docs/accessanalyzer/1.0/activitymonitoring/configuration/enablingsyslog.md delete mode 100644 docs/accessanalyzer/1.0/activitymonitoring/overview.md delete mode 100644 docs/accessanalyzer/1.0/activitymonitoring/viewingdata/_category_.json delete mode 100644 docs/accessanalyzer/1.0/activitymonitoring/viewingdata/fileaccessevents.md delete mode 100644 docs/accessanalyzer/1.0/activitymonitoring/viewingdata/useractivitypatterns.md delete mode 100644 docs/accessanalyzer/1.0/admin/_category_.json delete mode 100644 docs/accessanalyzer/1.0/admin/auditlogs/_category_.json delete mode 100644 docs/accessanalyzer/1.0/admin/auditlogs/export.md delete mode 100644 docs/accessanalyzer/1.0/admin/auditlogs/overview.md delete mode 100644 docs/accessanalyzer/1.0/admin/authentication/_category_.json delete mode 100644 docs/accessanalyzer/1.0/admin/authentication/overview.md delete mode 100644 docs/accessanalyzer/1.0/admin/authentication/sessionmonitoring.md delete mode 100644 docs/accessanalyzer/1.0/admin/authentication/tokenrefresh.md delete mode 100644 docs/accessanalyzer/1.0/admin/iam/_category_.json delete mode 100644 docs/accessanalyzer/1.0/admin/iam/identitiesentitlements.md delete mode 100644 docs/accessanalyzer/1.0/admin/iam/identitysync.md delete mode 100644 docs/accessanalyzer/1.0/admin/iam/overview.md delete mode 100644 docs/accessanalyzer/1.0/admin/iam/permissionpaths.md delete mode 100644 docs/accessanalyzer/1.0/admin/navigate/_category_.json delete mode 100644 docs/accessanalyzer/1.0/admin/navigate/datatables.md delete mode 100644 docs/accessanalyzer/1.0/admin/navigate/overview.md delete mode 100644 docs/accessanalyzer/1.0/admin/navigate/sidebar.md delete mode 100644 docs/accessanalyzer/1.0/admin/overview.md delete mode 100644 docs/accessanalyzer/1.0/admin/scans/_category_.json delete mode 100644 docs/accessanalyzer/1.0/admin/scans/executionhistory.md delete mode 100644 docs/accessanalyzer/1.0/admin/scans/overview.md delete mode 100644 docs/accessanalyzer/1.0/admin/scans/runningstop.md delete mode 100644 docs/accessanalyzer/1.0/admin/scans/scantypes.md delete mode 100644 docs/accessanalyzer/1.0/admin/scans/scheduling.md delete mode 100644 docs/accessanalyzer/1.0/admin/sensitivedata/_category_.json delete mode 100644 docs/accessanalyzer/1.0/admin/sensitivedata/customclassification.md delete mode 100644 docs/accessanalyzer/1.0/admin/sensitivedata/overview.md delete mode 100644 docs/accessanalyzer/1.0/admin/sensitivedata/patterngroups.md delete mode 100644 docs/accessanalyzer/1.0/admin/sensitivedata/taxonomygroups.md delete mode 100644 docs/accessanalyzer/1.0/admin/serviceaccounts/_category_.json delete mode 100644 docs/accessanalyzer/1.0/admin/serviceaccounts/associating.md delete mode 100644 docs/accessanalyzer/1.0/admin/serviceaccounts/credentialtypes.md delete mode 100644 docs/accessanalyzer/1.0/admin/serviceaccounts/overview.md delete mode 100644 docs/accessanalyzer/1.0/admin/settings/_category_.json delete mode 100644 docs/accessanalyzer/1.0/admin/settings/featureflags.md delete mode 100644 docs/accessanalyzer/1.0/admin/settings/overview.md delete mode 100644 docs/accessanalyzer/1.0/admin/settings/scanlimits.md delete mode 100644 docs/accessanalyzer/1.0/admin/settings/sessionttl.md delete mode 100644 docs/accessanalyzer/1.0/admin/sources/_category_.json delete mode 100644 docs/accessanalyzer/1.0/admin/sources/editdelete.md delete mode 100644 docs/accessanalyzer/1.0/admin/sources/overview.md delete mode 100644 docs/accessanalyzer/1.0/admin/sources/sourcegroups.md delete mode 100644 docs/accessanalyzer/1.0/admin/sources/sourcetypes.md delete mode 100644 docs/accessanalyzer/1.0/admin/sources/testconnections.md delete mode 100644 docs/accessanalyzer/1.0/admin/systemlogs.md delete mode 100644 docs/accessanalyzer/1.0/admin/users/_category_.json delete mode 100644 docs/accessanalyzer/1.0/admin/users/overview.md delete mode 100644 docs/accessanalyzer/1.0/admin/users/roles.md delete mode 100644 docs/accessanalyzer/1.0/admin/users/sessions.md delete mode 100644 docs/accessanalyzer/1.0/connectors/_category_.json delete mode 100644 docs/accessanalyzer/1.0/connectors/iam/_category_.json delete mode 100644 docs/accessanalyzer/1.0/connectors/iam/activedirectory/_category_.json delete mode 100644 docs/accessanalyzer/1.0/connectors/iam/activedirectory/connectionsetup.md delete mode 100644 docs/accessanalyzer/1.0/connectors/iam/activedirectory/customattributes.md delete mode 100644 docs/accessanalyzer/1.0/connectors/iam/activedirectory/groupmembership.md delete mode 100644 docs/accessanalyzer/1.0/connectors/iam/activedirectory/usergroupsync.md delete mode 100644 docs/accessanalyzer/1.0/connectors/iam/entraid/_category_.json delete mode 100644 docs/accessanalyzer/1.0/connectors/iam/entraid/appregistration.md delete mode 100644 docs/accessanalyzer/1.0/connectors/iam/entraid/certificateauth.md delete mode 100644 docs/accessanalyzer/1.0/connectors/iam/entraid/usergroupsync.md delete mode 100644 docs/accessanalyzer/1.0/connectors/iam/localgroups/_category_.json delete mode 100644 docs/accessanalyzer/1.0/connectors/iam/localgroups/powershellsetup.md delete mode 100644 docs/accessanalyzer/1.0/connectors/iam/localgroups/usergroupcollection.md delete mode 100644 docs/accessanalyzer/1.0/connectors/iam/overview.md delete mode 100644 docs/accessanalyzer/1.0/connectors/overview.md delete mode 100644 docs/accessanalyzer/1.0/connectors/source/_category_.json delete mode 100644 docs/accessanalyzer/1.0/connectors/source/cifs/_category_.json delete mode 100644 docs/accessanalyzer/1.0/connectors/source/cifs/connectionconfig.md delete mode 100644 docs/accessanalyzer/1.0/connectors/source/cifs/filevssharelevel.md delete mode 100644 docs/accessanalyzer/1.0/connectors/source/cifs/ntfspermissions.md delete mode 100644 docs/accessanalyzer/1.0/connectors/source/cifs/scandepthworkers.md delete mode 100644 docs/accessanalyzer/1.0/connectors/source/cifs/shareenumeration.md delete mode 100644 docs/accessanalyzer/1.0/connectors/source/overview.md delete mode 100644 docs/accessanalyzer/1.0/connectors/source/sharepointonline/_category_.json delete mode 100644 docs/accessanalyzer/1.0/connectors/source/sharepointonline/connectionconfig.md delete mode 100644 docs/accessanalyzer/1.0/connectors/source/sharepointonline/permissionsharinglinks.md delete mode 100644 docs/accessanalyzer/1.0/connectors/source/sharepointonline/scanningspecificsites.md delete mode 100644 docs/accessanalyzer/1.0/connectors/source/sharepointonline/sitelibraryenum.md delete mode 100644 docs/accessanalyzer/1.0/dashboards/_category_.json delete mode 100644 docs/accessanalyzer/1.0/dashboards/activedirectory.md delete mode 100644 docs/accessanalyzer/1.0/dashboards/copilotreadiness.md delete mode 100644 docs/accessanalyzer/1.0/dashboards/datasecurity.md delete mode 100644 docs/accessanalyzer/1.0/dashboards/entraid.md delete mode 100644 docs/accessanalyzer/1.0/dashboards/metabase/_category_.json delete mode 100644 docs/accessanalyzer/1.0/dashboards/metabase/accessingreports.md delete mode 100644 docs/accessanalyzer/1.0/dashboards/metabase/exportingdata.md delete mode 100644 docs/accessanalyzer/1.0/dashboards/metabase/savedreports.md delete mode 100644 docs/accessanalyzer/1.0/dashboards/overview.md delete mode 100644 docs/accessanalyzer/1.0/gettingstarted/_category_.json delete mode 100644 docs/accessanalyzer/1.0/gettingstarted/dashboardwalkthrough.md delete mode 100644 docs/accessanalyzer/1.0/gettingstarted/firstlogin.md delete mode 100644 docs/accessanalyzer/1.0/gettingstarted/firstscan/_category_.json delete mode 100644 docs/accessanalyzer/1.0/gettingstarted/firstscan/addingsource.md delete mode 100644 docs/accessanalyzer/1.0/gettingstarted/firstscan/configuringscan.md delete mode 100644 docs/accessanalyzer/1.0/gettingstarted/firstscan/overview.md delete mode 100644 docs/accessanalyzer/1.0/gettingstarted/firstscan/runningscan.md delete mode 100644 docs/accessanalyzer/1.0/gettingstarted/firstscan/viewingresults.md delete mode 100644 docs/accessanalyzer/1.0/gettingstarted/overview.md delete mode 100644 docs/accessanalyzer/1.0/overview/architecture.md rename docs/accessanalyzer/1.0/{ => overview}/install/_category_.json (100%) rename docs/accessanalyzer/1.0/{ => overview}/install/dspmctl.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/install/environmentvariables.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/install/network.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/install/overview.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/install/postinstall.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/install/preflight.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/install/quickinstall.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/install/requirements.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/install/security.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/install/ssl.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/install/stepbystep.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/install/uninstall.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/install/upgrade.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/requirements/_category_.json (100%) rename docs/accessanalyzer/1.0/{ => overview}/requirements/connectors/_category_.json (100%) rename docs/accessanalyzer/1.0/{ => overview}/requirements/connectors/activedirectory.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/requirements/connectors/cifs.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/requirements/connectors/entraid.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/requirements/connectors/localgroups.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/requirements/connectors/sharepointonline.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/requirements/database/_category_.json (100%) rename docs/accessanalyzer/1.0/{ => overview}/requirements/database/clickhouse.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/requirements/database/postgresql.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/requirements/database/redis.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/requirements/overview.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/requirements/system/_category_.json (100%) rename docs/accessanalyzer/1.0/{ => overview}/requirements/system/hardware.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/requirements/system/kubernetes.md (100%) rename docs/accessanalyzer/1.0/{ => overview}/requirements/system/network.md (100%) delete mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/_category_.json delete mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/overview.md delete mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/_category_.json delete mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/builtinpatterns.md delete mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/custompatterns.md delete mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/patterngroups.md delete mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/_category_.json delete mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/classificationbreakdown.md delete mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/matchcounts.md delete mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/runningscan.md delete mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/_category_.json delete mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/autovscustom.md delete mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/classificationrules.md delete mode 100644 docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/taxonomygroups.md delete mode 100644 docs/accessanalyzer/1.0/troubleshooting/_category_.json delete mode 100644 docs/accessanalyzer/1.0/troubleshooting/commonissues/_category_.json delete mode 100644 docs/accessanalyzer/1.0/troubleshooting/commonissues/connectionfailures.md delete mode 100644 docs/accessanalyzer/1.0/troubleshooting/commonissues/databaseconnectivity.md delete mode 100644 docs/accessanalyzer/1.0/troubleshooting/commonissues/scanerrors.md delete mode 100644 docs/accessanalyzer/1.0/troubleshooting/healthchecks/_category_.json delete mode 100644 docs/accessanalyzer/1.0/troubleshooting/healthchecks/endpoints.md delete mode 100644 docs/accessanalyzer/1.0/troubleshooting/healthchecks/probes.md delete mode 100644 docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/_category_.json delete mode 100644 docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/failedjobs.md delete mode 100644 docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/queues.md delete mode 100644 docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/sidekiq.md delete mode 100644 docs/accessanalyzer/1.0/troubleshooting/observability/_category_.json delete mode 100644 docs/accessanalyzer/1.0/troubleshooting/observability/opentelemetry.md delete mode 100644 docs/accessanalyzer/1.0/troubleshooting/observability/prometheus.md delete mode 100644 docs/accessanalyzer/1.0/troubleshooting/overview.md diff --git a/docs/accessanalyzer/1.0/activitymonitoring/_category_.json b/docs/accessanalyzer/1.0/activitymonitoring/_category_.json deleted file mode 100644 index 0855f40693..0000000000 --- a/docs/accessanalyzer/1.0/activitymonitoring/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Activity Monitoring", - "position": 90, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/activitymonitoring/configuration/_category_.json b/docs/accessanalyzer/1.0/activitymonitoring/configuration/_category_.json deleted file mode 100644 index 4fda61ea66..0000000000 --- a/docs/accessanalyzer/1.0/activitymonitoring/configuration/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Configuration", - "position": 20, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "enablingsyslog" - } -} diff --git a/docs/accessanalyzer/1.0/activitymonitoring/configuration/batchprocessing.md b/docs/accessanalyzer/1.0/activitymonitoring/configuration/batchprocessing.md deleted file mode 100644 index 807ec75106..0000000000 --- a/docs/accessanalyzer/1.0/activitymonitoring/configuration/batchprocessing.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Batch Processing Settings" -description: "Configure batch size and processing intervals" -sidebar_position: 30 -draft: true ---- - -# Batch Processing Settings diff --git a/docs/accessanalyzer/1.0/activitymonitoring/configuration/connectingnam.md b/docs/accessanalyzer/1.0/activitymonitoring/configuration/connectingnam.md deleted file mode 100644 index 3f9bdba5f0..0000000000 --- a/docs/accessanalyzer/1.0/activitymonitoring/configuration/connectingnam.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Connecting Netwrix Activity Monitor" -description: "Configure NAM to send events to Access Analyzer" -sidebar_position: 20 -draft: true ---- - -# Connecting Netwrix Activity Monitor diff --git a/docs/accessanalyzer/1.0/activitymonitoring/configuration/enablingsyslog.md b/docs/accessanalyzer/1.0/activitymonitoring/configuration/enablingsyslog.md deleted file mode 100644 index ed154c8585..0000000000 --- a/docs/accessanalyzer/1.0/activitymonitoring/configuration/enablingsyslog.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Enabling Syslog Ingestion" -description: "Enable the syslog listener for activity data" -sidebar_position: 10 -draft: true ---- - -# Enabling Syslog Ingestion diff --git a/docs/accessanalyzer/1.0/activitymonitoring/overview.md b/docs/accessanalyzer/1.0/activitymonitoring/overview.md deleted file mode 100644 index 1db4669826..0000000000 --- a/docs/accessanalyzer/1.0/activitymonitoring/overview.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Activity Monitoring" -description: "Monitor file access and user activity via Netwrix Activity Monitor" -sidebar_position: 1 -draft: true ---- - -# Activity Monitoring diff --git a/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/_category_.json b/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/_category_.json deleted file mode 100644 index 0f66039da8..0000000000 --- a/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Viewing Activity Data", - "position": 30, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "fileaccessevents" - } -} diff --git a/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/fileaccessevents.md b/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/fileaccessevents.md deleted file mode 100644 index e914857e32..0000000000 --- a/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/fileaccessevents.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "File Access Events" -description: "Viewing file access event data" -sidebar_position: 10 -draft: true ---- - -# File Access Events diff --git a/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/useractivitypatterns.md b/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/useractivitypatterns.md deleted file mode 100644 index b22d570ef1..0000000000 --- a/docs/accessanalyzer/1.0/activitymonitoring/viewingdata/useractivitypatterns.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "User Activity Patterns" -description: "Analyzing user activity trends and patterns" -sidebar_position: 20 -draft: true ---- - -# User Activity Patterns diff --git a/docs/accessanalyzer/1.0/admin/_category_.json b/docs/accessanalyzer/1.0/admin/_category_.json deleted file mode 100644 index 8ba9f88730..0000000000 --- a/docs/accessanalyzer/1.0/admin/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Administration", - "position": 50, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/admin/auditlogs/_category_.json b/docs/accessanalyzer/1.0/admin/auditlogs/_category_.json deleted file mode 100644 index 08737ee73a..0000000000 --- a/docs/accessanalyzer/1.0/admin/auditlogs/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Audit Logs", - "position": 100, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/admin/auditlogs/export.md b/docs/accessanalyzer/1.0/admin/auditlogs/export.md deleted file mode 100644 index 5f46de33f4..0000000000 --- a/docs/accessanalyzer/1.0/admin/auditlogs/export.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: "Log Export" -description: "Exporting audit log data" -sidebar_position: 20 ---- - -# Log Export - -Administrators can export audit log data for external analysis, compliance reporting, or long-term archival. The export feature generates a downloadable file containing the filtered audit log entries. - -## Exporting Logs - -To export audit logs: - -1. Navigate to **Audit Logs** in the sidebar. -2. Apply any desired filters (date range, user, action type, resource type) to narrow the export scope. -3. Click **Export**. -4. Select the export format: - -| Format | Description | -|---|---| -| **CSV** | Comma-separated values, compatible with spreadsheet applications and data analysis tools | -| **JSON** | Structured JSON format, suitable for programmatic processing and SIEM ingestion | - -5. Click **Download** to save the file. - -## Export Scope - -The export includes all audit log entries matching the current filter criteria. If no filters are applied, the export contains all available audit log records. - -:::note -Large exports may take several minutes to generate. The download begins automatically when the file is ready. -::: - -## Use Cases - -- **Compliance Audits** -- Provide auditors with a complete trail of administrative actions over a specified period. -- **SIEM Integration** -- Export logs in JSON format for ingestion into security information and event management platforms. -- **Archival** -- Periodically export and archive audit logs to external storage for long-term retention. - -:::warning -Exported audit log files may contain sensitive information about users and system configuration. Handle exported files in accordance with your organization's data handling policies. -::: diff --git a/docs/accessanalyzer/1.0/admin/auditlogs/overview.md b/docs/accessanalyzer/1.0/admin/auditlogs/overview.md deleted file mode 100644 index fa30bc76ae..0000000000 --- a/docs/accessanalyzer/1.0/admin/auditlogs/overview.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: "Audit Logs" -description: "Viewing system activity and audit trail" -sidebar_position: 10 ---- - -# Audit Logs - -Access Analyzer maintains a comprehensive audit trail of all user actions. Audit logs capture who performed an action, what was changed, and when the event occurred. This data supports security reviews, compliance audits, and incident investigations. - -## Viewing Audit Logs - -Navigate to **Audit Logs** in the sidebar to access the log viewer. The audit log table displays: - -| Column | Description | -|---|---| -| **Timestamp** | Date and time of the action | -| **User** | The user who performed the action | -| **Action** | The type of operation (e.g., Create, Update, Delete, Login, Logout) | -| **Resource** | The affected resource type and identifier | -| **Details** | Additional context about the change, including before and after values where applicable | -| **IP Address** | The client IP from which the action was performed | - -## Filtering and Searching - -Use the table controls to filter audit logs by: - -- **Date range** -- Specify start and end dates. -- **User** -- Filter by a specific user. -- **Action type** -- Show only specific action types. -- **Resource type** -- Filter by resource category (e.g., Source, Scan, User). - -## Log Retention - -Audit logs are retained for the duration configured in application settings. By default, logs are retained indefinitely. - -## Related Topics - -- [Log Export](/docs/accessanalyzer/1_0/admin/auditlogs/export) diff --git a/docs/accessanalyzer/1.0/admin/authentication/_category_.json b/docs/accessanalyzer/1.0/admin/authentication/_category_.json deleted file mode 100644 index b4206ec509..0000000000 --- a/docs/accessanalyzer/1.0/admin/authentication/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Authentication", - "position": 30, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/admin/authentication/overview.md b/docs/accessanalyzer/1.0/admin/authentication/overview.md deleted file mode 100644 index cea13a2a43..0000000000 --- a/docs/accessanalyzer/1.0/admin/authentication/overview.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: "Authentication" -description: "Login workflow and session lifecycle" -sidebar_position: 10 ---- - -# Authentication - -Access Analyzer uses session-based authentication backed by Redis for secure, server-side session storage. All API endpoints under `/api/v1/` require a valid session, except for the login endpoint. - -## Login Workflow - -1. The user submits their **username** and **password** via the login form. -2. The server validates the credentials against the stored Argon2id password hash. -3. On success, a new session is created in Redis and a session cookie is returned to the client. -4. The client includes the session cookie with all subsequent API requests. - -## Session Lifecycle - -Each session progresses through the following states: - -- **Active** -- The session is valid and the user is authenticated. -- **Refreshed** -- The session token has been refreshed before expiration. See [Token Refresh and Expiration](/docs/accessanalyzer/1_0/admin/authentication/tokenrefresh). -- **Expired** -- The session TTL has elapsed and the user must re-authenticate. -- **Revoked** -- An administrator has manually terminated the session. - -## IP Validation - -Access Analyzer validates the client IP address on each request. If a request originates from an IP that does not match the session's originating IP, the session is invalidated and the user must log in again. - -## Related Topics - -- [Token Refresh and Expiration](/docs/accessanalyzer/1_0/admin/authentication/tokenrefresh) -- [Session Monitoring and Revocation](/docs/accessanalyzer/1_0/admin/authentication/sessionmonitoring) diff --git a/docs/accessanalyzer/1.0/admin/authentication/sessionmonitoring.md b/docs/accessanalyzer/1.0/admin/authentication/sessionmonitoring.md deleted file mode 100644 index 15ad434a40..0000000000 --- a/docs/accessanalyzer/1.0/admin/authentication/sessionmonitoring.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: "Session Monitoring and Revocation" -description: "Monitoring active sessions and revoking access" -sidebar_position: 30 ---- - -# Session Monitoring and Revocation - -Administrators can monitor all active sessions across the application and revoke access when needed. This is useful for responding to security incidents or enforcing access policies. - -## Monitoring Active Sessions - -The session monitoring view is accessible from **Users** > **Sessions**. It provides a real-time view of all authenticated sessions, including: - -- **Username** and assigned role -- **Client IP address** and geographic context -- **Session start time** and **last activity** timestamp -- **Remaining TTL** before automatic expiration - -Use the table's filter and sort controls to locate specific sessions by user, IP address, or activity time. - -## Revoking Sessions - -To revoke one or more sessions: - -1. Select the target sessions using the row checkboxes. -2. Click **Revoke Selected**. -3. Confirm the action in the dialog. - -Revocation is immediate. The affected sessions are removed from Redis and all subsequent requests using those session tokens return `401 Unauthorized`. - -## Bulk Revocation - -To revoke all sessions for a specific user, navigate to the user's detail page and click **Revoke All Sessions**. This is recommended when a user account may be compromised. - -:::warning -Session revocation cannot be undone. Affected users must log in again to regain access. -::: diff --git a/docs/accessanalyzer/1.0/admin/authentication/tokenrefresh.md b/docs/accessanalyzer/1.0/admin/authentication/tokenrefresh.md deleted file mode 100644 index ee1dbd8250..0000000000 --- a/docs/accessanalyzer/1.0/admin/authentication/tokenrefresh.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: "Token Refresh and Expiration" -description: "How access tokens are refreshed and session expiration" -sidebar_position: 20 ---- - -# Token Refresh and Expiration - -Access Analyzer sessions have a configurable time-to-live (TTL). To prevent unnecessary re-authentication, sessions are automatically refreshed during active use. - -## How Token Refresh Works - -When a user makes an API request and the session is past the halfway point of its TTL, the server automatically issues a new session token. This process is transparent to the user: - -1. The client sends a request with the current session cookie. -2. The server detects that the session has passed 50% of its TTL. -3. A new session token is generated and the old token is invalidated. -4. The response includes the updated session cookie. - -## Session Expiration - -Sessions expire when the full TTL elapses without any qualifying refresh. When a session expires: - -- All subsequent API requests return a `401 Unauthorized` response. -- The user is redirected to the login page. -- The expired session record is automatically purged from Redis. - -## Configuration - -Session TTL and refresh behavior are configured in the application settings. See [Session and Token TTL](/docs/accessanalyzer/1_0/admin/settings/sessionttl) for configuration details. - -:::note -Token refresh only occurs during active requests. Background tabs or idle browser windows do not trigger a refresh. -::: diff --git a/docs/accessanalyzer/1.0/admin/iam/_category_.json b/docs/accessanalyzer/1.0/admin/iam/_category_.json deleted file mode 100644 index 762c39d494..0000000000 --- a/docs/accessanalyzer/1.0/admin/iam/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "IAM Services", - "position": 80, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/admin/iam/identitiesentitlements.md b/docs/accessanalyzer/1.0/admin/iam/identitiesentitlements.md deleted file mode 100644 index d0fedf9ee1..0000000000 --- a/docs/accessanalyzer/1.0/admin/iam/identitiesentitlements.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: "Viewing Identities and Entitlements" -description: "Browsing synced users and their permissions" -sidebar_position: 30 ---- - -# Viewing Identities and Entitlements - -After identity synchronization completes, administrators and viewers can browse the unified identity directory and review entitlements across all scanned sources. - -## Identity List - -Navigate to **IAM** > **Identities** to view all synced identities. The table displays: - -| Column | Description | -|---|---| -| **Display Name** | The user or group name | -| **Type** | User or Group | -| **Provider** | Source directory (Active Directory, Entra ID, Local Groups) | -| **Email** | Associated email address, if available | -| **Group Count** | Number of groups the identity belongs to | -| **Last Synced** | Timestamp of the most recent sync | - -Use the filter controls to narrow results by provider, type, or keyword search. - -## Entitlement Details - -Click an identity to open the detail view, which includes: - -- **Group Memberships** -- All groups the identity belongs to, including nested group membership. -- **Resource Access** -- A list of sources and resources the identity can access, with the effective permission level. -- **Permission Paths** -- Links to the [Permission Path Analysis](/docs/accessanalyzer/1_0/admin/iam/permissionpaths) for each access entry, showing how the permission was granted. - -## Cross-Provider Correlation - -When the same user exists in multiple directories, Access Analyzer correlates these identities and displays a unified view. Correlated accounts are indicated with a badge showing the linked providers. diff --git a/docs/accessanalyzer/1.0/admin/iam/identitysync.md b/docs/accessanalyzer/1.0/admin/iam/identitysync.md deleted file mode 100644 index 784bd209da..0000000000 --- a/docs/accessanalyzer/1.0/admin/iam/identitysync.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: "Identity Sync Process" -description: "How identities are synchronized from IAM providers" -sidebar_position: 20 ---- - -# Identity Sync Process - -Identity synchronization imports user and group data from configured IAM providers into Access Analyzer. This data forms the foundation for entitlement analysis and permission path reporting. - -## How Sync Works - -The identity sync process performs the following steps: - -1. Connects to each configured IAM source (Active Directory, Entra ID, or Local Groups) using the associated service account credentials. -2. Retrieves user accounts, groups, and membership relationships. -3. Normalizes identity data into a unified format across providers. -4. Stores the synchronized identities in the Access Analyzer database. -5. Correlates identities across multiple providers when the same user appears in more than one directory. - -## Triggering a Sync - -Identity sync occurs automatically during access scan execution. It can also be triggered manually: - -1. Navigate to **IAM** in the sidebar. -2. Click **Sync Now**. -3. Monitor the sync progress in the status indicator. - -## Sync Frequency - -Each access scan triggers a fresh identity sync for its target sources. For environments that change frequently, schedule access scans at regular intervals to keep identity data current. - -## Sync Status - -| Status | Description | -|---|---| -| **In Progress** | Sync is actively importing identity data | -| **Completed** | Sync finished successfully with a timestamp | -| **Failed** | Sync encountered an error; check system logs for details | - -:::note -Identity sync only imports identity metadata (usernames, group names, memberships). It does not import passwords or other credential data. -::: diff --git a/docs/accessanalyzer/1.0/admin/iam/overview.md b/docs/accessanalyzer/1.0/admin/iam/overview.md deleted file mode 100644 index 60b42bffc2..0000000000 --- a/docs/accessanalyzer/1.0/admin/iam/overview.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: "IAM Services" -description: "Configuring identity and access management integrations" -sidebar_position: 10 ---- - -# IAM Services - -The IAM section provides tools for synchronizing identities from external directories and analyzing access entitlements across your environment. This enables centralized visibility into who has access to what resources and how that access was granted. - -## Supported IAM Providers - -Access Analyzer synchronizes identity data from the following sources: - -| Provider | Identity Data | -|---|---| -| **Active Directory** | Users, groups, group memberships, organizational units | -| **Entra ID** | Users, groups, application role assignments | -| **Local Groups** | Local users and group memberships on Windows servers | - -## Key Capabilities - -- **Identity Synchronization** -- Import users and groups from configured IAM providers. See [Identity Sync Process](/docs/accessanalyzer/1_0/admin/iam/identitysync). -- **Identities and Entitlements** -- Browse synced identities and view their effective permissions across sources. See [Viewing Identities and Entitlements](/docs/accessanalyzer/1_0/admin/iam/identitiesentitlements). -- **Permission Path Analysis** -- Trace the path from a user to a resource to understand how access was granted. See [Permission Path Analysis](/docs/accessanalyzer/1_0/admin/iam/permissionpaths). - -## Prerequisites - -Before using IAM features, ensure that: - -- At least one Active Directory, Entra ID, or Local Groups source is configured with valid credentials. -- An access scan has been completed for the target sources. diff --git a/docs/accessanalyzer/1.0/admin/iam/permissionpaths.md b/docs/accessanalyzer/1.0/admin/iam/permissionpaths.md deleted file mode 100644 index c119a02184..0000000000 --- a/docs/accessanalyzer/1.0/admin/iam/permissionpaths.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: "Permission Path Analysis" -description: "Analyzing permission paths and access relationships" -sidebar_position: 40 ---- - -# Permission Path Analysis - -Permission path analysis traces the chain of access from an identity to a resource, showing every group membership, permission assignment, and inheritance step that grants access. This is essential for understanding why a user has access to a particular resource. - -## Viewing Permission Paths - -To view permission paths for a specific identity: - -1. Navigate to **IAM** > **Identities** and select the target identity. -2. In the **Resource Access** section, click the **View Path** link next to any resource entry. - -The permission path visualization displays the chain as a directional graph: - -**User** > **Group** > **Nested Group** > **Permission Assignment** > **Resource** - -## Path Components - -| Component | Description | -|---|---| -| **Identity** | The starting user or group | -| **Group Membership** | Direct or nested group that the identity belongs to | -| **Permission Entry** | The specific ACL or role assignment that grants access | -| **Resource** | The target file share, site, directory object, or folder | - -## Use Cases - -- **Access Reviews** -- Determine whether a user's access is appropriate and through which path it was granted. -- **Least Privilege Analysis** -- Identify overly broad group memberships that grant unintended access. -- **Incident Response** -- Trace access paths for a compromised account to assess the scope of exposure. - -:::note -Permission paths are computed from the most recent access scan results. Run a new scan to capture changes in group memberships or permission assignments. -::: diff --git a/docs/accessanalyzer/1.0/admin/navigate/_category_.json b/docs/accessanalyzer/1.0/admin/navigate/_category_.json deleted file mode 100644 index b9960d7f84..0000000000 --- a/docs/accessanalyzer/1.0/admin/navigate/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Navigating the Web Interface", - "position": 10, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/admin/navigate/datatables.md b/docs/accessanalyzer/1.0/admin/navigate/datatables.md deleted file mode 100644 index 4c976fa57d..0000000000 --- a/docs/accessanalyzer/1.0/admin/navigate/datatables.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: "Data Tables" -description: "Sorting, filtering, and pagination in data tables" -sidebar_position: 30 ---- - -# Data Tables - -Data tables are used throughout the Access Analyzer interface to display collections of records such as sources, scans, users, and audit log entries. Each table supports sorting, filtering, and pagination. - -## Sorting - -Click a column header to sort the table by that column. Click the same header again to toggle between ascending and descending order. A directional arrow icon indicates the current sort direction. - -## Filtering - -Use the filter controls above the table to narrow results: - -- **Text search** -- Enter a keyword to filter rows that match across visible columns. -- **Column filters** -- Some tables provide dropdown filters for specific columns such as status, type, or date range. - -## Pagination - -Tables with large datasets are paginated. Use the controls at the bottom of the table to: - -- Navigate between pages using **Previous** and **Next** buttons. -- Select the number of rows displayed per page (e.g., 10, 25, 50, 100). - -## Bulk Actions - -On supported tables, select one or more rows using the checkbox column to enable bulk actions. Available bulk actions vary by context and may include **Delete**, **Run Scan**, or **Export**. - -:::note -Table state (sort order, active filters, current page) resets when you navigate away from the page. -::: diff --git a/docs/accessanalyzer/1.0/admin/navigate/overview.md b/docs/accessanalyzer/1.0/admin/navigate/overview.md deleted file mode 100644 index 9662e7ffe0..0000000000 --- a/docs/accessanalyzer/1.0/admin/navigate/overview.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: "Navigating the Web Interface" -description: "Overview of the Access Analyzer web interface" -sidebar_position: 10 ---- - -# Navigating the Web Interface - -Netwrix Access Analyzer provides a web-based interface for managing all configuration and reporting tasks. The interface is organized into a persistent sidebar for primary navigation and a main content area that displays contextual data tables, forms, and dashboards. - -## Interface Layout - -The web interface consists of the following regions: - -- **Sidebar** -- The left-hand navigation panel provides access to all major sections including Sources, Scans, IAM, Sensitive Data, Settings, and Audit Logs. See [Sidebar Navigation](/docs/accessanalyzer/1_0/admin/navigate/sidebar) for details. -- **Header bar** -- Displays the current user, session status, and a logout control. -- **Main content area** -- Renders the active page content including data tables, detail views, and configuration forms. - -## Key Concepts - -- Most list views use paginated [Data Tables](/docs/accessanalyzer/1_0/admin/navigate/datatables) with sorting, filtering, and search capabilities. -- Breadcrumbs at the top of the content area indicate your current location in the navigation hierarchy. -- Action buttons such as **Create**, **Edit**, and **Delete** appear contextually based on the active page and your user role. - -:::note -The interface requires a modern web browser with JavaScript enabled. Supported browsers include the latest versions of Chrome, Edge, and Firefox. -::: diff --git a/docs/accessanalyzer/1.0/admin/navigate/sidebar.md b/docs/accessanalyzer/1.0/admin/navigate/sidebar.md deleted file mode 100644 index db30881ccf..0000000000 --- a/docs/accessanalyzer/1.0/admin/navigate/sidebar.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: "Sidebar Navigation" -description: "Using the sidebar to navigate between sections" -sidebar_position: 20 ---- - -# Sidebar Navigation - -The sidebar is the primary navigation element in the Access Analyzer web interface. It remains visible on every page and provides direct access to all major administration sections. - -## Sidebar Sections - -The sidebar contains the following top-level entries: - -| Section | Purpose | -|---|---| -| **Dashboard** | Application overview and summary metrics | -| **Sources** | Manage data sources and source groups | -| **Scans** | Create, schedule, and monitor scans | -| **IAM** | View synced identities, entitlements, and permission paths | -| **Sensitive Data** | Configure classification patterns and taxonomy rules | -| **Service Accounts** | Manage credentials for source connections | -| **Settings** | Application-wide configuration | -| **Audit Logs** | Review user action history | -| **System Logs** | View application and job processing logs | -| **Users** | Manage user accounts and sessions | - -## Collapsible Groups - -Some sidebar entries expand to reveal sub-items. Click a section label to toggle its children. The currently active page is highlighted with a visual indicator. - -## Role-Based Visibility - -Users with the **Viewer** role see a reduced sidebar. Administrative sections such as **Settings** and **Users** are hidden for non-administrator accounts. diff --git a/docs/accessanalyzer/1.0/admin/overview.md b/docs/accessanalyzer/1.0/admin/overview.md deleted file mode 100644 index 0b759ccd84..0000000000 --- a/docs/accessanalyzer/1.0/admin/overview.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: "Administration" -description: "Manage users, sources, scans, and system settings" -sidebar_position: 1 ---- - -# Administration - -The Administration section provides tools for configuring and managing all aspects of Netwrix Access Analyzer. From here, administrators can control user access, define data sources, configure scans, and maintain system settings. - -## Admin Sections - -| Section | Description | -|---|---| -| [Navigation](/docs/accessanalyzer/1_0/admin/navigate/overview) | Learn how to navigate the web interface, use the sidebar, and interact with data tables | -| [Users](/docs/accessanalyzer/1_0/admin/users/overview) | Create and manage user accounts, assign roles, and monitor sessions | -| [Authentication](/docs/accessanalyzer/1_0/admin/authentication/overview) | Configure login workflows, session lifecycle, and token management | -| [Sources](/docs/accessanalyzer/1_0/admin/sources/overview) | Add and manage data sources for scanning | -| [Service Accounts](/docs/accessanalyzer/1_0/admin/serviceaccounts/overview) | Manage credentials used to connect to data sources | -| [Scans](/docs/accessanalyzer/1_0/admin/scans/overview) | Create, schedule, and monitor access and sensitive data scans | -| [Sensitive Data](/docs/accessanalyzer/1_0/admin/sensitivedata/overview) | Configure classification patterns, taxonomy groups, and compliance mappings | -| [IAM](/docs/accessanalyzer/1_0/admin/iam/overview) | Synchronize identities and analyze entitlements and permission paths | -| [Settings](/docs/accessanalyzer/1_0/admin/settings/overview) | Configure application-wide settings, scan limits, and feature flags | -| [Audit Logs](/docs/accessanalyzer/1_0/admin/auditlogs/overview) | Review and export the full user action audit trail | -| [System Logs](/docs/accessanalyzer/1_0/admin/systemlogs) | View application-level system logs and Sidekiq job monitoring | - -:::note -Only users with the **Administrator** role have full access to all administration functions. Users with the **Viewer** role have read-only access. -::: diff --git a/docs/accessanalyzer/1.0/admin/scans/_category_.json b/docs/accessanalyzer/1.0/admin/scans/_category_.json deleted file mode 100644 index 27b262b756..0000000000 --- a/docs/accessanalyzer/1.0/admin/scans/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Scan Management", - "position": 60, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/admin/scans/executionhistory.md b/docs/accessanalyzer/1.0/admin/scans/executionhistory.md deleted file mode 100644 index 4afaf84df1..0000000000 --- a/docs/accessanalyzer/1.0/admin/scans/executionhistory.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: "Scan Execution History" -description: "Viewing scan status and execution history" -sidebar_position: 50 ---- - -# Scan Execution History - -Every scan execution is recorded with detailed status information, timing, and result summaries. The execution history provides a complete audit trail of all scan activity. - -## Viewing Execution History - -To view a scan's history: - -1. Navigate to **Scans** and click the target scan. -2. Select the **History** tab in the detail view. - -The history table displays each execution with the following columns: - -| Column | Description | -|---|---| -| **Run ID** | Unique identifier for the execution | -| **Status** | Final status (Completed, Failed, Stopped) | -| **Started At** | Timestamp when the execution began | -| **Completed At** | Timestamp when the execution ended | -| **Duration** | Total elapsed time | -| **Items Processed** | Number of resources scanned | -| **Findings** | Count of access entries or sensitive data matches found | - -## Execution Details - -Click a specific execution row to view detailed results including: - -- Per-source breakdown of items scanned and findings -- Error messages for failed executions -- Resource utilization metrics - -## Retention - -Execution history records are retained indefinitely. To manage storage, administrators can export and archive older records through the [Audit Logs](/docs/accessanalyzer/1_0/admin/auditlogs/overview) export feature. - -:::note -Execution history for deleted scans is also removed. Export any needed data before deleting a scan. -::: diff --git a/docs/accessanalyzer/1.0/admin/scans/overview.md b/docs/accessanalyzer/1.0/admin/scans/overview.md deleted file mode 100644 index fb917e14a4..0000000000 --- a/docs/accessanalyzer/1.0/admin/scans/overview.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: "Scan Management" -description: "Creating and managing scans" -sidebar_position: 10 ---- - -# Scan Management - -Scans are the core operational unit in Access Analyzer. A scan defines what sources to analyze, what type of analysis to perform, and when to execute. Administrators create and manage scans from the **Scans** section. - -## Creating Scans - -Scans are typically created as part of the **Connect Source** wizard (Step 3), where you configure scan types, options, and scheduling alongside the source group. The wizard creates all scans atomically with the source group and sources. - -Scans can also be managed independently after creation: - -1. Navigate to **Scans** in the sidebar. -2. Select a scan to view or edit its configuration. -3. Modify the schedule, scan options, or other settings. -4. Click **Save**. - -## Scan List - -The scan list displays all configured scans with their name, type, target sources, schedule, last execution status, and next scheduled run time. Use the data table controls to filter and sort. - -## Related Topics - -- [Scan Types](/docs/accessanalyzer/1_0/admin/scans/scantypes) -- [Scheduling Scans](/docs/accessanalyzer/1_0/admin/scans/scheduling) -- [Running and Stopping Scans](/docs/accessanalyzer/1_0/admin/scans/runningstop) -- [Scan Execution History](/docs/accessanalyzer/1_0/admin/scans/executionhistory) diff --git a/docs/accessanalyzer/1.0/admin/scans/runningstop.md b/docs/accessanalyzer/1.0/admin/scans/runningstop.md deleted file mode 100644 index 3df1773d7f..0000000000 --- a/docs/accessanalyzer/1.0/admin/scans/runningstop.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: "Running and Stopping Scans" -description: "Executing scans and graceful stop" -sidebar_position: 40 ---- - -# Running and Stopping Scans - -Administrators can manually trigger scan execution and control running scans through the web interface. These controls are available from the scan detail view and the scan list. - -## Running a Scan Manually - -To start a scan immediately: - -1. Navigate to **Scans** in the sidebar. -2. Locate the scan and click **Run** (or open the detail view and click **Run Now**). -3. The scan status changes to **Running** and progress is displayed in real time. - -## Scan Controls - -While a scan is running, the following controls are available: - -| Action | Description | -|---|---| -| **Pause** | Temporarily suspends scan execution. The scan can be resumed from where it stopped. | -| **Resume** | Continues a paused scan from its last checkpoint. | -| **Stop** | Initiates a graceful stop. The scan finishes processing the current item and then terminates. | - -## Scan Status Values - -| Status | Meaning | -|---|---| -| **Pending** | The scan is queued and waiting to start | -| **Running** | The scan is actively processing | -| **Paused** | The scan is suspended and can be resumed | -| **Completing** | The scan is finishing its current work unit after a stop request | -| **Completed** | The scan finished successfully | -| **Failed** | The scan terminated due to an error | - -:::warning -Stopping a scan does not roll back any data already collected. Partial results are retained and visible in the scan history. -::: diff --git a/docs/accessanalyzer/1.0/admin/scans/scantypes.md b/docs/accessanalyzer/1.0/admin/scans/scantypes.md deleted file mode 100644 index 39ba1911a2..0000000000 --- a/docs/accessanalyzer/1.0/admin/scans/scantypes.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: "Scan Types" -description: "Access, sensitive data, identity sync, and local users scan types" -sidebar_position: 20 ---- - -# Scan Types - -Access Analyzer supports several scan types, each designed to analyze different aspects of your data environment. Scan types are selected during the Connect Source wizard (Step 3) and determine what data is collected and reported. - -## Access Scans - -Access scans analyze permissions and access controls on the target sources. They collect: - -- User and group permission assignments -- Effective access rights -- Permission inheritance paths -- Share and folder-level access control lists - -Access scans are available for **CIFS** (File Server), **SharePoint**, **Active Directory**, and **Local Groups** source types. - -For File Server sources, access scans support additional configuration options including share filtering, scan depth, file-level permissions, hidden share enumeration, and worker threads. See [CIFS Connector](/docs/accessanalyzer/1_0/connectors/source/cifs/connectionconfig) for details. - -## Sensitive Data Scans - -Sensitive data scans inspect file content to identify data matching configured classification patterns. They detect: - -- Personally identifiable information (PII) -- Financial data (credit card numbers, bank account numbers) -- Protected health information (PHI) -- Credentials and secrets -- Custom patterns defined in [Sensitive Data Configuration](/docs/accessanalyzer/1_0/admin/sensitivedata/overview) - -Sensitive data scans are available for **CIFS** and **SharePoint** source types only. - -## Identity Sync Scans - -Identity sync scans retrieve users, groups, and permissions from identity providers: - -| Scan | Source Type | Description | -| --- | --- | --- | -| **Active Directory Inventory** | Active Directory | Synchronizes users, groups, OUs, and domain permissions | -| **Users, Groups and Roles** | Entra ID | Synchronizes Azure AD users, groups, directory roles, and optionally sensitivity labels | - -For Entra ID, the identity sync scan is always enabled and cannot be disabled. - -## Local Users and Groups Scans - -When an **Access** scan is enabled for a File Server source, a **Local Users and Groups** scan is automatically created alongside it. This scan collects local user and group account data from each file server, which is used to resolve local account references found in NTFS ACLs. - -This scan type does not require separate configuration — it inherits the same schedule as the access scan. - -## Comparison - -| Feature | Access Scan | Sensitive Data Scan | Identity Sync | Local Users and Groups | -|---|---|---|---|---| -| Analyzes permissions | Yes | No | No | No | -| Inspects file content | No | Yes | No | No | -| Syncs identities | No | No | Yes | Yes | -| Supported sources | CIFS, SharePoint, AD, Local Groups | CIFS, SharePoint | AD, Entra ID | CIFS (auto-created) | - -:::note -A single source can have multiple scan types configured independently, each with its own schedule. -::: diff --git a/docs/accessanalyzer/1.0/admin/scans/scheduling.md b/docs/accessanalyzer/1.0/admin/scans/scheduling.md deleted file mode 100644 index f1088e482d..0000000000 --- a/docs/accessanalyzer/1.0/admin/scans/scheduling.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: "Scheduling Scans" -description: "Configuring cron-based scan schedules" -sidebar_position: 30 ---- - -# Scheduling Scans - -Scans can be configured to run automatically on a recurring schedule using cron expressions. Scheduled scans are processed by the Sidekiq background job system. - -## Setting a Schedule - -To schedule a scan: - -1. Navigate to **Scans** and open the scan detail view. -2. Click **Edit**. -3. In the **Schedule** section, enable **Scheduled Execution**. -4. Enter a cron expression or use the visual schedule builder to define the frequency. -5. Click **Save**. - -## Cron Expression Format - -Schedules use standard five-field cron syntax: - -``` -* * * * * -| | | | | -| | | | +-- Day of week (0-6, Sunday=0) -| | | +---- Month (1-12) -| | +------ Day of month (1-31) -| +-------- Hour (0-23) -+---------- Minute (0-59) -``` - -**Examples:** - -| Expression | Description | -|---|---| -| `0 2 * * *` | Daily at 2:00 AM | -| `0 0 * * 0` | Weekly on Sunday at midnight | -| `0 6 1 * *` | Monthly on the 1st at 6:00 AM | -| `0 */4 * * *` | Every 4 hours | - -## Disabling a Schedule - -To stop a scan from running automatically, edit the scan and disable **Scheduled Execution**. The scan configuration is preserved and can be re-enabled later or run manually. - -:::note -All schedule times are interpreted in the server's configured timezone. -::: diff --git a/docs/accessanalyzer/1.0/admin/sensitivedata/_category_.json b/docs/accessanalyzer/1.0/admin/sensitivedata/_category_.json deleted file mode 100644 index 6b56ea467a..0000000000 --- a/docs/accessanalyzer/1.0/admin/sensitivedata/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Sensitive Data Configuration", - "position": 70, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/admin/sensitivedata/customclassification.md b/docs/accessanalyzer/1.0/admin/sensitivedata/customclassification.md deleted file mode 100644 index 732fcd762f..0000000000 --- a/docs/accessanalyzer/1.0/admin/sensitivedata/customclassification.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: "Custom Classification" -description: "Creating custom classification rules" -sidebar_position: 40 ---- - -# Custom Classification - -In addition to built-in patterns, administrators can create custom classification rules to detect organization-specific sensitive data types. Custom rules use regular expressions and integrate with the existing pattern and taxonomy group framework. - -## Creating a Custom Pattern - -To create a custom pattern: - -1. Navigate to **Sensitive Data** > **Pattern Groups**. -2. Select an existing group or click **Create Group** to define a new pattern group. -3. Click **Add Pattern**. -4. Complete the following fields: - -| Field | Description | -|---|---| -| **Name** | A descriptive label (e.g., "Internal Employee ID") | -| **Regex** | The regular expression to match against file content | -| **Confidence** | Expected accuracy level: **High**, **Medium**, or **Low** | -| **Description** | Optional notes about what the pattern detects | - -5. Click **Save**. - -## Creating a Custom Pattern Group - -Custom pattern groups organize related custom patterns under a shared label. To create a group: - -1. Click **Create Group** from the Pattern Groups page. -2. Enter a **Name** and optional **Description**. -3. Add one or more patterns to the group. -4. Click **Save**. - -## Mapping Custom Patterns to Taxonomy Groups - -To include custom patterns in compliance reporting, associate the custom pattern group with one or more taxonomy groups. Edit the taxonomy group and add the custom pattern group to its list of associated patterns. - -:::warning -Test custom regex patterns thoroughly before enabling them in production scans. Overly broad patterns can generate excessive false positives and impact scan performance. -::: diff --git a/docs/accessanalyzer/1.0/admin/sensitivedata/overview.md b/docs/accessanalyzer/1.0/admin/sensitivedata/overview.md deleted file mode 100644 index ba8d0bb074..0000000000 --- a/docs/accessanalyzer/1.0/admin/sensitivedata/overview.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: "Sensitive Data Configuration" -description: "Configuring patterns and classification rules" -sidebar_position: 10 ---- - -# Sensitive Data Configuration - -The Sensitive Data section allows administrators to configure how Access Analyzer identifies and classifies sensitive information during scans. Classification is driven by regex-based patterns organized into pattern groups and taxonomy groups. - -## How Classification Works - -During a sensitive data scan, Access Analyzer inspects file content against all enabled patterns. When a match is found, the file is tagged with the corresponding classification labels and compliance framework mappings. - -## Configuration Components - -| Component | Description | -|---|---| -| [Pattern Groups](/docs/accessanalyzer/1_0/admin/sensitivedata/patterngroups) | Collections of regex patterns that define what constitutes sensitive data (e.g., PII, Credentials) | -| [Taxonomy Groups](/docs/accessanalyzer/1_0/admin/sensitivedata/taxonomygroups) | Compliance-oriented groupings that map patterns to regulatory frameworks (e.g., GDPR, HIPAA) | -| [Custom Classification](/docs/accessanalyzer/1_0/admin/sensitivedata/customclassification) | User-defined patterns and rules for organization-specific data types | - -## Built-in Categories - -Access Analyzer ships with built-in patterns for common sensitive data categories: - -- **PII** -- Social Security numbers, email addresses, phone numbers, names -- **Credentials** -- API keys, passwords, connection strings, tokens -- **PHI** -- Medical record numbers, diagnosis codes, patient identifiers -- **Financial** -- Credit card numbers, bank account numbers, routing numbers - -:::note -Built-in patterns cannot be deleted but can be disabled if they are not relevant to your environment. -::: diff --git a/docs/accessanalyzer/1.0/admin/sensitivedata/patterngroups.md b/docs/accessanalyzer/1.0/admin/sensitivedata/patterngroups.md deleted file mode 100644 index 2179380a16..0000000000 --- a/docs/accessanalyzer/1.0/admin/sensitivedata/patterngroups.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: "Patterns and Pattern Groups" -description: "Managing regex patterns and pattern groups" -sidebar_position: 20 ---- - -# Patterns and Pattern Groups - -Patterns are regular expressions that Access Analyzer uses to identify sensitive data within file content. Patterns are organized into groups for easier management and selective enablement. - -## Pattern Groups - -A pattern group is a named collection of related patterns. Built-in groups include: - -| Group | Examples | -|---|---| -| **PII** | Social Security numbers, driver's license numbers, passport numbers | -| **Credentials** | API keys, passwords in config files, SSH private keys | -| **PHI** | Medical record numbers, health plan IDs, diagnosis codes | -| **Financial** | Credit card numbers (Visa, MasterCard, Amex), IBAN, routing numbers | - -## Managing Patterns - -To view and manage patterns within a group: - -1. Navigate to **Sensitive Data** > **Pattern Groups**. -2. Select a group to view its patterns. -3. Each pattern displays its name, regex expression, and enabled/disabled status. - -Administrators can enable or disable individual patterns within a group. Disabled patterns are excluded from scan matching. - -## Pattern Fields - -| Field | Description | -|---|---| -| **Name** | Descriptive label for the pattern | -| **Regex** | The regular expression used for matching | -| **Confidence** | Expected match accuracy (High, Medium, Low) | -| **Enabled** | Whether the pattern is active during scans | - -:::note -Changes to pattern enablement take effect on the next scan execution. Running scans use the configuration that was active at scan start time. -::: diff --git a/docs/accessanalyzer/1.0/admin/sensitivedata/taxonomygroups.md b/docs/accessanalyzer/1.0/admin/sensitivedata/taxonomygroups.md deleted file mode 100644 index ff36f4f0b9..0000000000 --- a/docs/accessanalyzer/1.0/admin/sensitivedata/taxonomygroups.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: "Taxonomy Groups and Rules" -description: "Configuring taxonomy-based data classification" -sidebar_position: 30 ---- - -# Taxonomy Groups and Rules - -Taxonomy groups map pattern detections to compliance frameworks and regulatory standards. They provide a compliance-oriented view of sensitive data findings. - -## Built-in Compliance Mappings - -Access Analyzer includes pre-configured taxonomy groups aligned to major regulatory frameworks: - -| Taxonomy Group | Framework | Relevant Data Types | -|---|---|---| -| **GDPR** | General Data Protection Regulation | PII, personal data, EU resident identifiers | -| **CCPA** | California Consumer Privacy Act | PII, consumer records, financial identifiers | -| **HIPAA** | Health Insurance Portability and Accountability Act | PHI, medical records, health plan data | -| **PCI DSS** | Payment Card Industry Data Security Standard | Credit card numbers, cardholder data | -| **GLBA** | Gramm-Leach-Bliley Act | Financial records, account numbers | -| **CMMC** | Cybersecurity Maturity Model Certification | Controlled unclassified information, credentials | - -## How Taxonomy Mapping Works - -Each taxonomy group references one or more pattern groups. When a sensitive data scan produces a match against a pattern, the finding is automatically tagged with all associated taxonomy labels. This enables compliance-focused reporting without additional configuration. - -## Managing Taxonomy Groups - -To view taxonomy group configuration: - -1. Navigate to **Sensitive Data** > **Taxonomy Groups**. -2. Select a group to view its associated patterns and compliance mappings. - -Administrators can enable or disable taxonomy groups to control which compliance labels appear in scan results. - -:::note -Built-in taxonomy groups are updated with product releases to reflect changes in regulatory standards. -::: diff --git a/docs/accessanalyzer/1.0/admin/serviceaccounts/_category_.json b/docs/accessanalyzer/1.0/admin/serviceaccounts/_category_.json deleted file mode 100644 index 85d0158bb9..0000000000 --- a/docs/accessanalyzer/1.0/admin/serviceaccounts/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Service Accounts", - "position": 50, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/admin/serviceaccounts/associating.md b/docs/accessanalyzer/1.0/admin/serviceaccounts/associating.md deleted file mode 100644 index cd3479356a..0000000000 --- a/docs/accessanalyzer/1.0/admin/serviceaccounts/associating.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: "Associating with Sources" -description: "Linking service accounts to data sources" -sidebar_position: 30 ---- - -# Associating with Sources - -Each data source requires an associated service account to authenticate when connecting to the target environment. A single service account can be shared across multiple sources of compatible types. - -## Assigning a Service Account to a Source - -Service accounts are assigned during source creation or by editing an existing source: - -1. Navigate to **Sources** and open the source detail view. -2. Click **Edit**. -3. In the **Service Account** field, select the desired account from the dropdown. -4. Click **Save**. - -The dropdown only shows service accounts with a credential type compatible with the selected source type. - -## Changing the Associated Account - -To switch a source to a different service account, edit the source and select a new account. The change takes effect on the next scan execution. Running scans continue to use the previously assigned account until completion. - -## Disassociating a Service Account - -To remove a service account association, edit the source and clear the **Service Account** field, then assign a replacement. Sources cannot be saved without a service account. - -:::note -Verify connectivity after changing service account associations by running a [Test Connection](/docs/accessanalyzer/1_0/admin/sources/testconnections). -::: - -## Compatibility Matrix - -| Source Type | Username/Password | OAuth2 Client Credentials | Certificate | -|---|---|---|---| -| CIFS | Yes | No | No | -| SharePoint | No | Yes | Yes | -| Active Directory | Yes | No | No | -| Entra ID | No | Yes | Yes | -| Local Groups | Yes | No | No | diff --git a/docs/accessanalyzer/1.0/admin/serviceaccounts/credentialtypes.md b/docs/accessanalyzer/1.0/admin/serviceaccounts/credentialtypes.md deleted file mode 100644 index 7dc69e4b2f..0000000000 --- a/docs/accessanalyzer/1.0/admin/serviceaccounts/credentialtypes.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: "Credential Types" -description: "Supported credential types and configurations" -sidebar_position: 20 ---- - -# Credential Types - -Access Analyzer supports three credential types for service accounts. The appropriate type depends on the target source and its authentication requirements. Service accounts can be created ahead of time from the **Service Accounts** page, or inline during the Connect Source wizard. - -## Supported Types - -| Credential Type | Description | Typical Use | -|---|---|---| -| **Username/Password** | Standard username and password pair | CIFS file shares, Active Directory, Local Groups | -| **OAuth2 Client Credentials** | Client ID and client secret for OAuth2 flows | Entra ID | -| **Certificate** | X.509 certificate with private key | SharePoint Online | - -## Username/Password - -Provide a **Username** and **Password**. The password is encrypted at rest. For Active Directory and file server sources, use the `DOMAIN\username` or `username@domain.com` format. - -Used by the **File Server** and **Active Directory** wizards. During the wizard, click **+ Create New Account** to create a username/password service account inline. - -## OAuth2 Client Credentials - -Provide a **Client ID** and **Client Secret**. These credentials are used in the OAuth2 client credentials grant flow to obtain an access token from the identity provider. - -Used by the **Entra ID** wizard. The Client ID and Client Secret come from an Azure AD app registration — see [App Registration and Permissions](/docs/accessanalyzer/1_0/connectors/iam/entraid/appregistration) for setup instructions. - -## Certificate - -Upload a **Certificate** file (PEM or PFX format) and provide the **Private Key** or PFX password. Certificate-based authentication is used for SharePoint Online connections. - -:::note -Credential values are stored encrypted and cannot be viewed after creation. To update credentials, edit the service account and provide new values. -::: diff --git a/docs/accessanalyzer/1.0/admin/serviceaccounts/overview.md b/docs/accessanalyzer/1.0/admin/serviceaccounts/overview.md deleted file mode 100644 index aed048051c..0000000000 --- a/docs/accessanalyzer/1.0/admin/serviceaccounts/overview.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: "Service Accounts" -description: "Managing credentials for data source connections" -sidebar_position: 10 ---- - -# Service Accounts - -Service accounts store the credentials that Access Analyzer uses to connect to and authenticate against data sources. Each service account is configured with a specific credential type and can be associated with one or more sources. - -## Creating a Service Account - -To create a service account: - -1. Navigate to **Service Accounts** in the sidebar. -2. Click **Create Service Account**. -3. Enter a **Name** and optional **Description**. -4. Select the [credential type](/docs/accessanalyzer/1_0/admin/serviceaccounts/credentialtypes) (Username/Password, OAuth2 Client Credentials, or Certificate). -5. Provide the required credential fields. -6. Click **Save**. - -## Service Account List - -The service account list displays all configured accounts with their name, credential type, number of associated sources, and creation date. Credentials are never displayed in plaintext after initial creation. - -## Editing and Deleting - -- **Edit** -- Update the name, description, or credential values. Changing credentials takes effect on the next scan execution. -- **Delete** -- Remove a service account. This operation fails if the account is currently associated with any sources. - -:::warning -Before deleting a service account, disassociate it from all sources. See [Associating with Sources](/docs/accessanalyzer/1_0/admin/serviceaccounts/associating). -::: diff --git a/docs/accessanalyzer/1.0/admin/settings/_category_.json b/docs/accessanalyzer/1.0/admin/settings/_category_.json deleted file mode 100644 index 2e922ee742..0000000000 --- a/docs/accessanalyzer/1.0/admin/settings/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Application Settings", - "position": 90, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/admin/settings/featureflags.md b/docs/accessanalyzer/1.0/admin/settings/featureflags.md deleted file mode 100644 index e40dbea10d..0000000000 --- a/docs/accessanalyzer/1.0/admin/settings/featureflags.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: "Feature Flags" -description: "Runtime feature toggles and configuration" -sidebar_position: 40 ---- - -# Feature Flags - -Feature flags allow administrators to enable or disable specific application capabilities at runtime without restarting the service. Flags are defined in the `app_settings.yml` configuration file and can be overridden through the web interface. - -## Viewing Feature Flags - -Navigate to **Settings** > **Feature Flags** to see all available flags, their current state, and descriptions. - -## Configuration File - -Feature flags are declared in `app_settings.yml` on the application server: - -```yaml -feature_flags: - sensitive_data_scanning: true - identity_correlation: true - audit_log_export: true - advanced_permission_paths: false -``` - -## Overriding via the Web Interface - -To toggle a feature flag: - -1. Navigate to **Settings** > **Feature Flags**. -2. Locate the flag and toggle its state. -3. Click **Save**. - -Web interface overrides take precedence over values in `app_settings.yml`. To revert to the file-based value, click **Reset to Default** next to the flag. - -## Common Feature Flags - -| Flag | Description | -|---|---| -| `sensitive_data_scanning` | Enables or disables the sensitive data scan type | -| `identity_correlation` | Enables cross-provider identity matching in IAM | -| `audit_log_export` | Enables the audit log export functionality | -| `advanced_permission_paths` | Enables detailed permission path visualization | - -:::warning -Disabling a feature flag immediately removes the associated functionality from the web interface for all users. Running operations that depend on a disabled flag may fail. -::: diff --git a/docs/accessanalyzer/1.0/admin/settings/overview.md b/docs/accessanalyzer/1.0/admin/settings/overview.md deleted file mode 100644 index f7268f3fb5..0000000000 --- a/docs/accessanalyzer/1.0/admin/settings/overview.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: "Application Settings" -description: "Global application configuration options" -sidebar_position: 10 ---- - -# Application Settings - -The Settings section provides administrators with controls over global application behavior. Configuration changes made here affect all users and system operations. - -## Settings Categories - -| Category | Description | -|---|---| -| [Concurrent Scan Limits](/docs/accessanalyzer/1_0/admin/settings/scanlimits) | Control the maximum number of scans that can execute simultaneously | -| [Session and Token TTL](/docs/accessanalyzer/1_0/admin/settings/sessionttl) | Configure session duration and token refresh intervals | -| [Feature Flags](/docs/accessanalyzer/1_0/admin/settings/featureflags) | Enable or disable application features at runtime | - -## Accessing Settings - -Navigate to **Settings** in the sidebar. Only users with the **Administrator** role can view and modify settings. - -## Saving Changes - -After modifying a setting, click **Save** to apply the change. Most settings take effect immediately. Settings that require a service restart display a notification indicating when the change will be applied. - -:::warning -Changing application settings can affect system behavior for all users. Review changes carefully before saving, and coordinate with other administrators when modifying production configurations. -::: - -## Configuration File - -Some advanced settings are managed through the `app_settings.yml` configuration file on the server. Settings modified through the web interface override values in the configuration file. See [Feature Flags](/docs/accessanalyzer/1_0/admin/settings/featureflags) for details on file-based configuration. diff --git a/docs/accessanalyzer/1.0/admin/settings/scanlimits.md b/docs/accessanalyzer/1.0/admin/settings/scanlimits.md deleted file mode 100644 index 8711666a0c..0000000000 --- a/docs/accessanalyzer/1.0/admin/settings/scanlimits.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: "Concurrent Scan Limits" -description: "Configuring maximum concurrent scan execution" -sidebar_position: 20 ---- - -# Concurrent Scan Limits - -Access Analyzer limits the number of scans that can run simultaneously to manage system resource consumption. Administrators configure these limits based on available server capacity. - -## Configuration - -To configure scan limits: - -1. Navigate to **Settings** in the sidebar. -2. Locate the **Concurrent Scan Limits** section. -3. Set the desired values and click **Save**. - -## Available Settings - -| Setting | Description | Default | -|---|---|---| -| **Max Concurrent Access Scans** | Maximum number of access scans running at the same time | 5 | -| **Max Concurrent Sensitive Data Scans** | Maximum number of sensitive data scans running at the same time | 3 | -| **Max Total Concurrent Scans** | Combined limit across all scan types | 8 | - -## Behavior When Limits Are Reached - -When a scan is triggered (manually or by schedule) and the concurrent limit has been reached, the scan enters a **Pending** state and is queued. Queued scans start automatically as running scans complete, in first-in-first-out order. - -:::note -Sensitive data scans are typically more resource-intensive than access scans. Consider setting a lower concurrent limit for sensitive data scans to avoid impacting system performance. -::: - -## Monitoring - -View the current number of running and queued scans from the **Scans** list page. The status column indicates whether each scan is **Running**, **Pending**, or **Queued**. diff --git a/docs/accessanalyzer/1.0/admin/settings/sessionttl.md b/docs/accessanalyzer/1.0/admin/settings/sessionttl.md deleted file mode 100644 index 00d6f81382..0000000000 --- a/docs/accessanalyzer/1.0/admin/settings/sessionttl.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: "Session and Token TTL" -description: "Configuring session duration and token refresh intervals" -sidebar_position: 30 ---- - -# Session and Token TTL - -Session and token TTL (time-to-live) settings control how long user sessions remain valid and when tokens are refreshed. These settings balance security requirements with user convenience. - -## Configuration - -To configure session TTL: - -1. Navigate to **Settings** in the sidebar. -2. Locate the **Session Configuration** section. -3. Adjust the values and click **Save**. - -## Available Settings - -| Setting | Description | Default | -|---|---|---| -| **Session TTL** | Maximum lifetime of a session, in minutes | 480 (8 hours) | -| **Idle Timeout** | Time of inactivity before a session expires, in minutes | 60 | -| **Token Refresh Threshold** | Percentage of TTL elapsed before automatic token refresh occurs | 50% | - -## How TTL Affects Users - -- When the **Session TTL** expires, the user is logged out regardless of activity. -- When the **Idle Timeout** elapses without any API requests, the session expires. -- Active sessions are automatically refreshed when the elapsed time exceeds the **Token Refresh Threshold**, extending the session without user intervention. - -See [Token Refresh and Expiration](/docs/accessanalyzer/1_0/admin/authentication/tokenrefresh) for details on the refresh mechanism. - -:::warning -Setting very long session TTLs increases the window of exposure if a session token is compromised. Follow your organization's security policies when configuring these values. -::: - -## Session Storage - -Sessions are stored in Redis. Ensure the Redis instance has sufficient memory to accommodate all active sessions, especially in environments with many concurrent users. diff --git a/docs/accessanalyzer/1.0/admin/sources/_category_.json b/docs/accessanalyzer/1.0/admin/sources/_category_.json deleted file mode 100644 index ac24200ff0..0000000000 --- a/docs/accessanalyzer/1.0/admin/sources/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Data Source Management", - "position": 40, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/admin/sources/editdelete.md b/docs/accessanalyzer/1.0/admin/sources/editdelete.md deleted file mode 100644 index 41b634770e..0000000000 --- a/docs/accessanalyzer/1.0/admin/sources/editdelete.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: "Editing and Deleting Sources" -description: "Modifying and removing data sources" -sidebar_position: 40 ---- - -# Editing and Deleting Sources - -Administrators can modify source configuration or remove sources that are no longer needed. Both operations are available from the source detail view. - -## Editing a Source - -To edit a source: - -1. Navigate to **Sources** and click the target source to open its detail view. -2. Click **Edit**. -3. Update the desired fields such as connection parameters, display name, or associated service account. -4. Click **Save**. - -:::note -The source type cannot be changed after creation. To use a different type, create a new source and delete the old one. -::: - -## Deleting a Source - -To delete a source: - -1. Open the source detail view. -2. Click **Delete**. -3. Confirm the deletion in the dialog. - -:::warning -Deleting a source removes all associated scan configurations and execution history. This action cannot be undone. Export any required scan results before deleting. -::: - -## Impact on Related Resources - -- **Scans** -- Any scans targeting the deleted source are also removed. -- **Source Groups** -- The source is automatically removed from any groups it belonged to. -- **Scan Results** -- Historical scan result data associated with the source is permanently deleted. diff --git a/docs/accessanalyzer/1.0/admin/sources/overview.md b/docs/accessanalyzer/1.0/admin/sources/overview.md deleted file mode 100644 index f23e5217a5..0000000000 --- a/docs/accessanalyzer/1.0/admin/sources/overview.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: "Data Source Management" -description: "Adding and managing data sources" -sidebar_position: 10 ---- - -# Data Source Management - -Sources represent the target environments that Access Analyzer connects to for scanning. Sources are organized into **source groups** — named collections that share a service account and configuration. Administrators create, edit, test, and delete sources from the **Sources** section. - -## Adding Sources - -Sources are created through the **Connect Source** wizard, a 3-step guided workflow: - -1. Navigate to **Sources** in the sidebar. -2. Click **Connect Source** to open the wizard drawer. -3. **Step 1** — Select the [source type](/docs/accessanalyzer/1_0/admin/sources/sourcetypes) (File Server, Active Directory, Entra ID, or SharePoint). -4. **Step 2** — Name the source group, assign a [service account](/docs/accessanalyzer/1_0/admin/serviceaccounts/overview), and add one or more sources. -5. **Step 3** — Configure scan types, scan options, and scheduling. -6. Click **Complete Setup** to create the source group, sources, and scans in one operation. - -The wizard uses the `POST /v1/source-groups/setup` endpoint to create all resources atomically. - -### Source Group Behavior by Type - -| Source Type | Sources per Group | Notes | -| --- | --- | --- | -| **File Server** | Multiple | Add many servers with shared service account and domain | -| **Active Directory** | Multiple | Add multiple domain controllers | -| **Entra ID** | Single | One Azure AD tenant per group | -| **SharePoint Online** | Multiple | Add multiple site collections | - -## Source List - -The sources list displays all configured sources with their name, type, connection status, and associated service account. Use the data table controls to filter by type or search by name. - -## Related Topics - -- [Source Types and Configuration](/docs/accessanalyzer/1_0/admin/sources/sourcetypes) -- [Testing Connections](/docs/accessanalyzer/1_0/admin/sources/testconnections) -- [Editing and Deleting Sources](/docs/accessanalyzer/1_0/admin/sources/editdelete) -- [Source Groups](/docs/accessanalyzer/1_0/admin/sources/sourcegroups) diff --git a/docs/accessanalyzer/1.0/admin/sources/sourcegroups.md b/docs/accessanalyzer/1.0/admin/sources/sourcegroups.md deleted file mode 100644 index 13bce1ba62..0000000000 --- a/docs/accessanalyzer/1.0/admin/sources/sourcegroups.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -title: "Source Groups" -description: "Organizing sources into groups with shared configuration" -sidebar_position: 50 ---- - -# Source Groups - -A source group is a named collection of related sources that share a common service account, configuration, and scan settings. Source groups are the primary organizational unit for sources in Access Analyzer. - -## How Source Groups Work - -Source groups are created through the **Connect Source** wizard, which creates the group, all its sources, and associated scans in a single atomic operation. Each source group has: - -- A **name** to identify the group -- A **source type** (all sources in the group are the same type) -- A **service account** shared by all sources in the group -- One or more **sources** (the actual connection targets) -- One or more **scans** with a shared schedule - -## Source Groups by Type - -| Source Type | Sources per Group | Example | -| --- | --- | --- | -| **File Server** | Multiple servers | `Finance File Servers` with `fs01`, `fs02`, `fs03` — all sharing one service account and domain | -| **Active Directory** | Multiple domain controllers | `Corp AD` with `dc01`, `dc02` | -| **Entra ID** | Single tenant | `Corporate Entra ID` with one Azure AD tenant | -| **SharePoint Online** | Multiple site collections | `Marketing SharePoint` with several sites | - -## Creating a Source Group - -Source groups are created exclusively through the Connect Source wizard: - -1. Navigate to **Sources** in the sidebar -2. Click **Connect Source** -3. Follow the 3-step wizard: select source type, configure sources, set up scans -4. Click **Complete Setup** - -For detailed instructions, see [Adding a Data Source](/docs/accessanalyzer/1_0/gettingstarted/firstscan/addingsource). - -## Viewing Source Groups - -The sources list displays individual sources, each showing its parent source group. You can filter by source group to see all sources within a group. - -## Deleting a Source Group - -Deleting a source group removes the group, all its sources, and all associated scans. - -:::warning -Deleting a source group is permanent and removes all sources and scan configurations within it. Scan execution history is preserved for audit purposes. -::: diff --git a/docs/accessanalyzer/1.0/admin/sources/sourcetypes.md b/docs/accessanalyzer/1.0/admin/sources/sourcetypes.md deleted file mode 100644 index 55f2f7cc4d..0000000000 --- a/docs/accessanalyzer/1.0/admin/sources/sourcetypes.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: "Source Types and Configuration" -description: "Available source types and their configuration parameters" -sidebar_position: 20 ---- - -# Source Types and Configuration - -Access Analyzer supports multiple source types, each targeting a different data environment. The source type determines the required connection parameters and the kinds of scans available. - -## Available Source Types - -| Source Type | Description | Supported Scans | -|---|---|---| -| **CIFS** | Windows file shares accessed via SMB/CIFS protocol | Access, Sensitive Data | -| **SharePoint** | Microsoft SharePoint Online or on-premises sites | Access, Sensitive Data | -| **Active Directory** | On-premises Active Directory domains | Access | -| **Entra ID** | Microsoft Entra ID (formerly Azure AD) tenants | Access | -| **Local Groups** | Local user and group membership on Windows servers | Access | - -## Configuration Parameters - -Each source type requires specific connection details: - -- **CIFS** -- Server hostname or IP, share path, and port number. -- **SharePoint** -- Site URL, authentication method, and tenant ID. -- **Active Directory** -- Domain controller hostname, base DN, and LDAP port. -- **Entra ID** -- Tenant ID, client ID, and authentication secret or certificate. -- **Local Groups** -- Target server hostname or IP address. - -All source types require an associated [service account](/docs/accessanalyzer/1_0/admin/serviceaccounts/overview) with appropriate credentials for the target environment. - -:::note -Source type cannot be changed after creation. To switch types, delete the existing source and create a new one. -::: diff --git a/docs/accessanalyzer/1.0/admin/sources/testconnections.md b/docs/accessanalyzer/1.0/admin/sources/testconnections.md deleted file mode 100644 index ff5de9a3c1..0000000000 --- a/docs/accessanalyzer/1.0/admin/sources/testconnections.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: "Testing Connections" -description: "Validating source connectivity before scanning" -sidebar_position: 30 ---- - -# Testing Connections - -Before running scans, verify that Access Analyzer can reach and authenticate to each configured source using the test connection feature. Connection testing is available both during source creation (in the wizard) and on existing sources. - -## Testing During Source Creation - -The Connect Source wizard includes a **Test Connection** button in Step 2: - -- **File Server** — Tests all servers in parallel. Each server shows its own status: **Connected** (green), **Failed** (red), or **Testing** (spinner). A summary toast shows the overall result (for example, "All 3 connections successful" or "1 of 3 failed"). -- **Entra ID** — Tests the OAuth2 connection to the specified Azure AD tenant. Status appears inline: "Successfully connected to Entra ID" or "Connection failed" with an error message. -- **Active Directory** — Tests connectivity to each domain controller. - -:::note -Connection testing in the wizard is non-blocking. You can proceed to the next step regardless of test results. -::: - -## Testing Existing Sources - -To test an existing source connection: - -1. Navigate to **Sources** in the sidebar. -2. Locate the source in the list and click its row to open the detail view. -3. Click **Test Connection**. -4. Wait for the test to complete. Results appear inline. - -## What Gets Tested - -The test connection operation sends a request to `POST /v1/sources/test-connection` with the source's connection parameters. It validates: - -| Check | Description | -|---|---| -| **Network Reachability** | Confirms the target host and port are accessible from the application server | -| **Authentication** | Verifies the associated service account credentials are accepted | -| **Authorization** | Confirms the service account has sufficient permissions to read the target data | - -## Troubleshooting - -If a connection test fails: - -- Verify the source hostname, port, and path are correct. -- Confirm the service account credentials have not expired or been rotated. -- Check that network firewalls allow traffic between the Access Analyzer server and the target host. -- For Entra ID, verify the Tenant ID is correct and the app registration has the required API permissions. -- Review [System Logs](/docs/accessanalyzer/1_0/admin/systemlogs) for detailed error messages. - -:::note -Connection tests do not scan data. They only validate that the connection can be established and authenticated. -::: diff --git a/docs/accessanalyzer/1.0/admin/systemlogs.md b/docs/accessanalyzer/1.0/admin/systemlogs.md deleted file mode 100644 index 383d3646d2..0000000000 --- a/docs/accessanalyzer/1.0/admin/systemlogs.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: "System Logs" -description: "Viewing and exporting system log data" -sidebar_position: 110 ---- - -# System Logs - -System logs provide visibility into the internal operations of Access Analyzer, including application events, background job processing, and error diagnostics. These logs are distinct from audit logs, which track user actions. - -## Viewing System Logs - -Navigate to **System Logs** in the sidebar to access the log viewer. System logs display application-level events including: - -- Application startup and shutdown events -- Background job execution (scan workers, identity sync) -- Connection errors and retry attempts -- API request errors and exceptions - -## Sidekiq Dashboard - -Access Analyzer uses Sidekiq for background job processing. The Sidekiq dashboard provides real-time monitoring of: - -| View | Description | -|---|---| -| **Queues** | Active job queues and their current depth | -| **Workers** | Currently executing jobs and their runtime | -| **Retries** | Failed jobs scheduled for automatic retry | -| **Dead** | Jobs that have exhausted all retry attempts | -| **Scheduled** | Jobs queued for future execution | - -Access the Sidekiq dashboard from **System Logs** > **Job Monitor**. - -## Log Levels - -System logs are categorized by severity: - -| Level | Description | -|---|---| -| **ERROR** | Failures requiring attention | -| **WARN** | Unexpected conditions that did not cause failures | -| **INFO** | Normal operational events | -| **DEBUG** | Detailed diagnostic output (disabled by default) | - -:::note -Debug-level logging generates significant output and can impact performance. Enable it only for targeted troubleshooting and disable it afterward. -::: diff --git a/docs/accessanalyzer/1.0/admin/users/_category_.json b/docs/accessanalyzer/1.0/admin/users/_category_.json deleted file mode 100644 index 9633707491..0000000000 --- a/docs/accessanalyzer/1.0/admin/users/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "User Management", - "position": 20, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/admin/users/overview.md b/docs/accessanalyzer/1.0/admin/users/overview.md deleted file mode 100644 index 74de4204be..0000000000 --- a/docs/accessanalyzer/1.0/admin/users/overview.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: "User Management" -description: "Creating and managing user accounts" -sidebar_position: 10 ---- - -# User Management - -Access Analyzer supports multi-user access with role-based permissions. Administrators can create, edit, and deactivate user accounts from the **Users** section of the web interface. - -## Creating a User - -To create a new user: - -1. Navigate to **Users** in the sidebar. -2. Click **Create User**. -3. Enter the required fields: **Username**, **Email**, and **Password**. -4. Assign a [role](/docs/accessanalyzer/1_0/admin/users/roles) (Administrator or Viewer). -5. Click **Save**. - -Passwords are hashed using Argon2id before storage. Users must meet the configured password complexity requirements. - -## Managing Users - -From the users list, administrators can: - -- **Edit** a user to update their email, role, or password. -- **Deactivate** a user to revoke access without deleting the account record. -- **Delete** a user to permanently remove the account. - -:::warning -Deleting a user is irreversible. Consider deactivating accounts instead if you need to preserve audit history. -::: - -## Related Topics - -- [Roles and Permissions](/docs/accessanalyzer/1_0/admin/users/roles) -- [Session Management](/docs/accessanalyzer/1_0/admin/users/sessions) diff --git a/docs/accessanalyzer/1.0/admin/users/roles.md b/docs/accessanalyzer/1.0/admin/users/roles.md deleted file mode 100644 index 9c83c8f400..0000000000 --- a/docs/accessanalyzer/1.0/admin/users/roles.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: "Roles and Permissions" -description: "Admin and Viewer role definitions and access levels" -sidebar_position: 20 ---- - -# Roles and Permissions - -Access Analyzer uses a role-based access control model with two built-in roles. Each user is assigned exactly one role at account creation, which determines their access level throughout the application. - -## Role Definitions - -| Capability | Administrator | Viewer | -|---|---|---| -| View dashboards and reports | Yes | Yes | -| View sources, scans, and results | Yes | Yes | -| Create, edit, and delete sources | Yes | No | -| Create, schedule, and run scans | Yes | No | -| Manage service accounts | Yes | No | -| Configure sensitive data rules | Yes | No | -| Manage users and roles | Yes | No | -| Modify application settings | Yes | No | -| View audit logs | Yes | Yes | -| Export audit logs | Yes | No | - -## Administrator - -The **Administrator** role grants full access to all features, including user management, source configuration, scan execution, settings, and audit log exports. At least one administrator account must exist in the system. - -## Viewer - -The **Viewer** role provides read-only access to dashboards, scan results, source listings, and audit logs. Viewers cannot create, modify, or delete any resources. - -:::note -Role assignments can be changed at any time by an administrator through the user edit form. -::: diff --git a/docs/accessanalyzer/1.0/admin/users/sessions.md b/docs/accessanalyzer/1.0/admin/users/sessions.md deleted file mode 100644 index 7af8472d7f..0000000000 --- a/docs/accessanalyzer/1.0/admin/users/sessions.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: "Session Management" -description: "Viewing and managing active user sessions" -sidebar_position: 30 ---- - -# Session Management - -Access Analyzer maintains session state for all authenticated users using Redis-backed server-side sessions. Administrators can view and manage active sessions from the **Users** section. - -## Viewing Active Sessions - -Navigate to **Users** > **Sessions** to see a list of all active sessions. The table displays: - -| Column | Description | -|---|---| -| **User** | The username associated with the session | -| **IP Address** | The client IP from which the session was created | -| **Created At** | Timestamp when the session was initiated | -| **Last Active** | Timestamp of the most recent request | -| **Expires At** | When the session will automatically expire based on the configured TTL | - -## Revoking Sessions - -To revoke a session, select the target row and click **Revoke**. The user will be immediately logged out and must re-authenticate. Administrators can also revoke all sessions for a specific user from the user detail page. - -## Session Security - -- Sessions are validated against the originating IP address. If the client IP changes, the session is invalidated. -- Session TTL is configurable in [Settings](/docs/accessanalyzer/1_0/admin/settings/sessionttl). -- Idle sessions expire automatically after the configured timeout period. - -:::warning -Revoking a session takes effect immediately. The affected user will lose access to any in-progress work that has not been saved. -::: diff --git a/docs/accessanalyzer/1.0/connectors/_category_.json b/docs/accessanalyzer/1.0/connectors/_category_.json deleted file mode 100644 index f7b8ad38d7..0000000000 --- a/docs/accessanalyzer/1.0/connectors/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Connectors", - "position": 60, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/connectors/iam/_category_.json b/docs/accessanalyzer/1.0/connectors/iam/_category_.json deleted file mode 100644 index 47506a72c8..0000000000 --- a/docs/accessanalyzer/1.0/connectors/iam/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "IAM Connectors", - "position": 10, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/connectors/iam/activedirectory/_category_.json b/docs/accessanalyzer/1.0/connectors/iam/activedirectory/_category_.json deleted file mode 100644 index 365d3210fe..0000000000 --- a/docs/accessanalyzer/1.0/connectors/iam/activedirectory/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Active Directory", - "position": 10, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "connectionsetup" - } -} diff --git a/docs/accessanalyzer/1.0/connectors/iam/activedirectory/connectionsetup.md b/docs/accessanalyzer/1.0/connectors/iam/activedirectory/connectionsetup.md deleted file mode 100644 index 3dbcd27070..0000000000 --- a/docs/accessanalyzer/1.0/connectors/iam/activedirectory/connectionsetup.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: "Connection Setup" -description: "Configuring the Active Directory LDAP connection" -sidebar_position: 10 ---- - -# Connection Setup - -Configure the Active Directory connector to synchronize users and groups from your on-premises directory. - -## Prerequisites - -- A domain service account with read access to directory objects — see [Active Directory Requirements](/docs/accessanalyzer/1_0/requirements/connectors/activedirectory) -- Network connectivity from the Access Analyzer VM to a domain controller on port 389 (LDAP) or 636 (LDAPS) - -## Create a Service Account - -1. Navigate to **Service Accounts** in the sidebar -2. Click **Add Service Account** -3. Enter a **Name** (for example, `AD Read-Only Service Account`) -4. Select **Username/Password** as the type -5. Enter the **Username** in `DOMAIN\username` or `user@domain.com` format -6. Enter the **Password** -7. Click **Add service account** - -## Add Active Directory as a Source - -1. Navigate to **Configuration** > **Sources** -2. Click **Add Source** -3. Select **IAM Source** as the category -4. Select **Active Directory** as the source type -5. Select the service account created above -6. Enter the **Host** (domain controller hostname or IP) -7. Enter the **Port** (`389` for LDAP, `636` for LDAPS) -8. Enter the **Domain** (for example, `corp.example.com`) -9. Click **Test Connection** to verify connectivity -10. After a successful test, click **Create Source** - -## Test Connection - -The test connection validates: - -- Network connectivity to the domain controller -- LDAP bind with the provided credentials -- Ability to query directory objects - -If the test fails, verify the domain controller is reachable on the specified port and the credentials are correct. diff --git a/docs/accessanalyzer/1.0/connectors/iam/activedirectory/customattributes.md b/docs/accessanalyzer/1.0/connectors/iam/activedirectory/customattributes.md deleted file mode 100644 index fb620e0bb8..0000000000 --- a/docs/accessanalyzer/1.0/connectors/iam/activedirectory/customattributes.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: "Custom Attributes" -description: "Collecting custom LDAP attributes" -sidebar_position: 40 -draft: true ---- - -# Custom Attributes - -:::note -Custom LDAP attribute collection is planned for a future release of Access Analyzer. This page will be updated when the feature becomes available. -::: diff --git a/docs/accessanalyzer/1.0/connectors/iam/activedirectory/groupmembership.md b/docs/accessanalyzer/1.0/connectors/iam/activedirectory/groupmembership.md deleted file mode 100644 index 397959033f..0000000000 --- a/docs/accessanalyzer/1.0/connectors/iam/activedirectory/groupmembership.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: "Group Membership Mapping" -description: "Transitive group membership resolution" -sidebar_position: 30 ---- - -# Group Membership Mapping - -Access Analyzer resolves transitive (nested) group memberships to build a complete picture of effective access. - -## How It Works - -The Active Directory connector collects: - -1. **Direct memberships** — Users and groups that are immediate members of a group -2. **Nested memberships** — Groups that are members of other groups, creating a hierarchy - -Access Analyzer flattens these hierarchies to determine **effective membership** — the complete list of groups a user belongs to, whether directly or through nesting. - -## Impact on Access Analysis - -Effective group memberships are mapped to entitlements discovered by source connector scans, enabling Access Analyzer to show: - -- All groups that grant a user access to a resource -- Whether access comes from direct or nested group membership -- Overly permissive access through deeply nested group chains diff --git a/docs/accessanalyzer/1.0/connectors/iam/activedirectory/usergroupsync.md b/docs/accessanalyzer/1.0/connectors/iam/activedirectory/usergroupsync.md deleted file mode 100644 index 3be2c6e33e..0000000000 --- a/docs/accessanalyzer/1.0/connectors/iam/activedirectory/usergroupsync.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: "User and Group Sync" -description: "Synchronizing users and groups from Active Directory" -sidebar_position: 20 ---- - -# User and Group Sync - -The Active Directory connector performs a full synchronization of users, groups, and group memberships. - -## What Gets Synchronized - -| Object Type | Data Collected | -| --- | --- | -| **Users** | Display name, SAM account name, UPN, email, distinguished name, enabled status | -| **Groups** | Group name, type (security/distribution), scope (domain local/global/universal), distinguished name | -| **Group memberships** | Direct and nested membership relationships | - -## Running a Sync - -1. Navigate to **Configuration** > **Scans** -2. Create or select a scan configured for the Active Directory source -3. Run the scan — the connector performs a full sync on each execution - -## Sync Behavior - -- Each sync is a **full synchronization** — all users, groups, and memberships are collected -- The connector uses LDAP3 for directory queries -- Duration depends on directory size (number of users and groups) -- Results are stored in the Access Analyzer database and used for identity-to-entitlement mapping diff --git a/docs/accessanalyzer/1.0/connectors/iam/entraid/_category_.json b/docs/accessanalyzer/1.0/connectors/iam/entraid/_category_.json deleted file mode 100644 index d1dd3ba163..0000000000 --- a/docs/accessanalyzer/1.0/connectors/iam/entraid/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Entra ID", - "position": 20, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "appregistration" - } -} diff --git a/docs/accessanalyzer/1.0/connectors/iam/entraid/appregistration.md b/docs/accessanalyzer/1.0/connectors/iam/entraid/appregistration.md deleted file mode 100644 index cdc2d7edef..0000000000 --- a/docs/accessanalyzer/1.0/connectors/iam/entraid/appregistration.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -title: "App Registration and Permissions" -description: "Azure AD app registration and API permissions for Entra ID" -sidebar_position: 10 ---- - -# App Registration and Permissions - -The Entra ID connector uses an Azure AD app registration with OAuth2 client credentials for authentication. You need to create an app registration in Azure and then add its credentials as a service account in Access Analyzer. - -## Create an App Registration - -1. Sign in to the [Azure portal](https://portal.azure.com) -2. Navigate to **Microsoft Entra ID** > **App registrations** -3. Click **New registration** -4. Enter a name (for example, `Netwrix Access Analyzer - Entra ID`) -5. Leave the redirect URI blank -6. Click **Register** - -## Configure API Permissions - -1. In the app registration, go to **API permissions** -2. Click **Add a permission** > **Microsoft Graph** > **Application permissions** -3. Add the following permissions: - - `User.Read.All` - - `Group.Read.All` -4. Click **Grant admin consent** for the permissions - -## Create a Client Secret - -1. Go to **Certificates & secrets** -2. Click **New client secret** -3. Enter a description and expiration period -4. Click **Add** -5. Copy the **Value** immediately — it is not shown again - -## Add Entra ID as a Source in Access Analyzer - -Entra ID sources are created through the **Connect Source** wizard, which guides you through a 3-step process: - -### Step 1 — Select Source Type - -1. Navigate to **Configuration** > **Sources** in Access Analyzer -2. Click **Connect Source** to open the wizard drawer -3. Select **Entra ID** from the source type cards -4. Click **Next** - -### Step 2 — Configure Entra ID - -1. Enter a **Source Group Name** (for example, `Corporate Entra ID`) -2. Select or create a **Service Account**: - - Click **+ Create New Account** to add a new Entra ID service account - - Enter the **Client ID** (Application ID from Azure) and **Client Secret** - - Or select an existing Entra ID service account from the dropdown -3. Enter the **Tenant ID** — this is the Azure AD directory ID in UUID format (for example, `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`) -4. Optionally click **Test Connection** to verify OAuth2 authentication - -:::note -The test connection validates that Access Analyzer can authenticate to the Microsoft Graph API with the provided credentials. Testing is optional — you can proceed without testing. -::: - -### Step 3 — Set Up a Scan - -1. The **Users, Groups and Roles** scan is automatically enabled (cannot be disabled) -2. Configure any additional sync options (for example, **Sync Sensitivity Labels**) -3. Choose when to run the first scan: now, at a scheduled time, or on a recurring schedule -4. Click **Complete Setup** - -After setup, the source group is created and the scan runs according to your selected schedule. - -## Related Topics - -- [User and Group Sync](/docs/accessanalyzer/1_0/connectors/iam/entraid/usergroupsync) — What data is synchronized -- [Entra ID Requirements](/docs/accessanalyzer/1_0/requirements/connectors/entraid) — Permissions and prerequisites diff --git a/docs/accessanalyzer/1.0/connectors/iam/entraid/certificateauth.md b/docs/accessanalyzer/1.0/connectors/iam/entraid/certificateauth.md deleted file mode 100644 index a92d6d15ab..0000000000 --- a/docs/accessanalyzer/1.0/connectors/iam/entraid/certificateauth.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: "Certificate-Based Authentication" -description: "Configuring certificate authentication for Entra ID" -sidebar_position: 30 -draft: true ---- - -# Certificate-Based Authentication - -:::note -Certificate-based authentication for Entra ID is planned for a future release. In v1.0, the Entra ID connector uses OAuth2 client credentials (client secret) authentication. See [App Registration and Permissions](/docs/accessanalyzer/1_0/connectors/iam/entraid/appregistration). -::: diff --git a/docs/accessanalyzer/1.0/connectors/iam/entraid/usergroupsync.md b/docs/accessanalyzer/1.0/connectors/iam/entraid/usergroupsync.md deleted file mode 100644 index 73f1d48a42..0000000000 --- a/docs/accessanalyzer/1.0/connectors/iam/entraid/usergroupsync.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: "User and Group Sync" -description: "Synchronizing users, groups, and roles from Entra ID" -sidebar_position: 20 ---- - -# User and Group Sync - -The Entra ID connector synchronizes users, groups, and roles from your Azure AD tenant into Access Analyzer. This data is used for identity mapping and entitlement analysis across your data sources. - -## What Gets Synchronized - -| Data | Description | -| --- | --- | -| **Users** | All user accounts in the tenant, including display name, UPN, and account status | -| **Groups** | Security groups and Microsoft 365 groups, including membership | -| **Roles** | Directory roles assigned to users and groups | -| **Sensitivity Labels** | Microsoft Purview sensitivity labels (optional — see [Sync Options](#sync-options) below) | - -## How It Works - -When you create an Entra ID source group through the [Connect Source wizard](/docs/accessanalyzer/1_0/gettingstarted/firstscan/addingsource), a **Users, Groups and Roles** scan is automatically configured. This scan is always enabled and cannot be disabled — it runs every time the Entra ID source is scanned. - -The connector authenticates using OAuth2 client credentials and calls the Microsoft Graph API to retrieve identity data from the specified tenant. - -## Sync Options - -During scan setup (Step 3 of the wizard), additional sync options may be available depending on the source type metadata configured on the backend. For example: - -- **Sync Sensitivity Labels** — When enabled, the connector also retrieves Microsoft Purview sensitivity labels assigned to users and groups - -These options appear as toggle switches below the scan type selector on the scan setup page. - -## Scan Scheduling - -The Users, Groups and Roles scan supports three scheduling modes: - -| Mode | Description | -| --- | --- | -| **Run scan now** | Execute immediately after setup completes | -| **Run scan at** | Schedule for a specific date and time | -| **Advanced scheduling** | Configure a recurring cron schedule | - -## Related Topics - -- [App Registration and Permissions](/docs/accessanalyzer/1_0/connectors/iam/entraid/appregistration) — Azure AD setup requirements -- [Entra ID Requirements](/docs/accessanalyzer/1_0/requirements/connectors/entraid) — Permissions and prerequisites diff --git a/docs/accessanalyzer/1.0/connectors/iam/localgroups/_category_.json b/docs/accessanalyzer/1.0/connectors/iam/localgroups/_category_.json deleted file mode 100644 index 19a04b0aec..0000000000 --- a/docs/accessanalyzer/1.0/connectors/iam/localgroups/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Local Groups", - "position": 30, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "powershellsetup" - } -} diff --git a/docs/accessanalyzer/1.0/connectors/iam/localgroups/powershellsetup.md b/docs/accessanalyzer/1.0/connectors/iam/localgroups/powershellsetup.md deleted file mode 100644 index 0144b61557..0000000000 --- a/docs/accessanalyzer/1.0/connectors/iam/localgroups/powershellsetup.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: "PowerShell Remoting Setup" -description: "Configuring WinRM and PowerShell Remoting for Local Groups collection" -sidebar_position: 10 ---- - -# PowerShell Remoting Setup - -The Local Groups connector uses PowerShell Remoting (WinRM) to enumerate local users and groups on Windows machines. - -## Prerequisites - -- WinRM must be enabled on each target machine -- A service account with local administrator access or membership in the Remote Management Users group -- Network connectivity from Access Analyzer to target machines on port 5985 (HTTP) or 5986 (HTTPS) - -## Enable WinRM on Target Machines - -### Single Machine - -Run the following command in an elevated PowerShell prompt: - -```powershell -Enable-PSRemoting -Force -``` - -### Domain-Wide via Group Policy - -1. Open **Group Policy Management** -2. Navigate to **Computer Configuration** > **Administrative Templates** > **Windows Components** > **Windows Remote Management (WinRM)** > **WinRM Service** -3. Enable **Allow remote server management through WinRM** -4. Set the IPv4/IPv6 filter to `*` or specific IP ranges - -## Create a Service Account - -1. Navigate to **Service Accounts** in Access Analyzer -2. Click **Add Service Account** -3. Enter a **Name** (for example, `Local Groups - WinRM`) -4. Select **Username/Password** as the type -5. Enter the **Username** in `MACHINE\username` or `DOMAIN\username` format -6. Enter the **Password** -7. Click **Add service account** - -## Add Local Groups as a Source - -1. Navigate to **Configuration** > **Sources** -2. Click **Add Source** > **IAM Source** > **Local Groups** -3. Select the service account -4. Enter the **Host** (target machine hostname or IP) -5. Enter the **Port** (`5985` for HTTP, `5986` for HTTPS) -6. Click **Test Connection** -7. Click **Create Source** diff --git a/docs/accessanalyzer/1.0/connectors/iam/localgroups/usergroupcollection.md b/docs/accessanalyzer/1.0/connectors/iam/localgroups/usergroupcollection.md deleted file mode 100644 index 2fed900d2b..0000000000 --- a/docs/accessanalyzer/1.0/connectors/iam/localgroups/usergroupcollection.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: "Local User and Group Collection" -description: "Collecting local users and groups from target machines" -sidebar_position: 20 ---- - -# Local User and Group Collection - -The Local Groups connector collects local users, local groups, and group memberships from Windows machines via PowerShell Remoting. - -## What Gets Collected - -| Object Type | Data Collected | -| --- | --- | -| **Local users** | Username, full name, description, enabled status, last logon | -| **Local groups** | Group name, description, type | -| **Group memberships** | Local group members (local users and domain accounts/groups) | - -## Running a Sync - -1. Navigate to **Configuration** > **Scans** -2. Create or select a scan configured for the Local Groups source -3. Run the scan — the connector performs a sync on each execution - -## How It Works - -The connector: - -1. Establishes a WinRM session to the target machine -2. Executes PowerShell commands to enumerate local users and groups -3. Collects group membership information, including domain accounts that are members of local groups -4. Returns results to the Core API for storage and analysis - -## Use Cases - -Local group collection is useful for: - -- Identifying domain accounts with local administrator access -- Mapping local group memberships that grant file share permissions -- Detecting overly permissive local group configurations diff --git a/docs/accessanalyzer/1.0/connectors/iam/overview.md b/docs/accessanalyzer/1.0/connectors/iam/overview.md deleted file mode 100644 index e0f373519b..0000000000 --- a/docs/accessanalyzer/1.0/connectors/iam/overview.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: "IAM Connectors" -description: "Identity and access management connectors" -sidebar_position: 1 ---- - -# IAM Connectors - -IAM (Identity and Access Management) connectors synchronize identity data — users, groups, and group memberships — from identity providers into Access Analyzer. This data is used to map who has access to what across your data sources. - -## Available IAM Connectors - -| Connector | Identity Provider | Operations | Credential Type | -| --- | --- | --- | --- | -| [Active Directory](/docs/accessanalyzer/1_0/connectors/iam/activedirectory/connectionsetup) | On-premises AD | Test connection, Full sync | Username / Password | -| [Entra ID](/docs/accessanalyzer/1_0/connectors/iam/entraid/appregistration) | Microsoft Entra ID | Test connection only | OAuth2 Client Credentials | -| [Local Groups](/docs/accessanalyzer/1_0/connectors/iam/localgroups/powershellsetup) | Windows local accounts | Test connection, Sync | Username / Password | - -:::note -The Entra ID connector in v1.0 supports test connection only. Full identity synchronization will be available in a future release. -::: diff --git a/docs/accessanalyzer/1.0/connectors/overview.md b/docs/accessanalyzer/1.0/connectors/overview.md deleted file mode 100644 index e3c68accb8..0000000000 --- a/docs/accessanalyzer/1.0/connectors/overview.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: "Connectors" -description: "Connector architecture, types, and lifecycle" -sidebar_position: 1 ---- - -# Connectors - -Connectors are the components that communicate with external data sources and identity providers on behalf of Access Analyzer. Each connector handles authentication, data collection, and state management for its target system. - -## Connector Types - -| Category | Purpose | Connectors | -| --- | --- | --- | -| **IAM Connectors** | Synchronize identities (users, groups, memberships) from identity providers | [Active Directory](/docs/accessanalyzer/1_0/connectors/iam/activedirectory/connectionsetup), [Entra ID](/docs/accessanalyzer/1_0/connectors/iam/entraid/appregistration), [Local Groups](/docs/accessanalyzer/1_0/connectors/iam/localgroups/powershellsetup) | -| **Source Connectors** | Scan data repositories for files, permissions, and content | [CIFS/SMB](/docs/accessanalyzer/1_0/connectors/source/cifs/connectionconfig), [SharePoint Online](/docs/accessanalyzer/1_0/connectors/source/sharepointonline/connectionconfig) | - -## Connector Operations - -| Operation | Description | -| --- | --- | -| **Test connection** | Validates credentials and network connectivity | -| **Access scan** | Enumerates files, folders, and permissions on a data source | -| **Sync** | Synchronizes users, groups, and memberships from an identity provider | -| **Get object** | Retrieves specific objects or metadata from the target system | - -## Connector Execution - -Connectors run as Kubernetes Jobs managed by the Connector API. When a scan or sync is triggered: - -1. The Core API creates a scan execution record -2. The Connector API launches a Kubernetes Job with the appropriate connector -3. The connector authenticates using the associated service account -4. Data is collected and sent back to the Core API for processing -5. The job completes and reports its final status - -## State Management - -| Connector | Pause/Resume | -| --- | --- | -| CIFS/SMB | Supported | -| All others | Not supported | diff --git a/docs/accessanalyzer/1.0/connectors/source/_category_.json b/docs/accessanalyzer/1.0/connectors/source/_category_.json deleted file mode 100644 index 895acef0a9..0000000000 --- a/docs/accessanalyzer/1.0/connectors/source/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Source Connectors", - "position": 20, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/connectors/source/cifs/_category_.json b/docs/accessanalyzer/1.0/connectors/source/cifs/_category_.json deleted file mode 100644 index 6e8930174e..0000000000 --- a/docs/accessanalyzer/1.0/connectors/source/cifs/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "CIFS / SMB File Shares", - "position": 10, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "connectionconfig" - } -} diff --git a/docs/accessanalyzer/1.0/connectors/source/cifs/connectionconfig.md b/docs/accessanalyzer/1.0/connectors/source/cifs/connectionconfig.md deleted file mode 100644 index 433e9c371a..0000000000 --- a/docs/accessanalyzer/1.0/connectors/source/cifs/connectionconfig.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -title: "Connection Configuration" -description: "Configuring CIFS/SMB connection parameters" -sidebar_position: 10 ---- - -# Connection Configuration - -Configure the CIFS/SMB connector to scan Windows file shares for files, folders, and access permissions. File server sources are created through the **Connect Source** wizard, which supports adding multiple servers in a single source group. - -## Prerequisites - -- A service account with read access to target shares — see [CIFS Requirements](/docs/accessanalyzer/1_0/requirements/connectors/cifs) -- Network connectivity from Access Analyzer to each file server on port 445 - -## Creating a File Server Source Group - -File server sources are created through the 3-step **Connect Source** wizard: - -### Step 1 — Select Source Type - -1. Navigate to **Configuration** > **Sources** -2. Click **Connect Source** to open the wizard drawer -3. Select **File Server** from the source type cards -4. Click **Next** - -### Step 2 — Configure File Server - -1. Enter a **Source Group Name** (for example, `Finance File Servers`) -2. Select or create a **Service Account**: - - Click **+ Create New Account** to add a new username/password account - - Or select an existing service account from the dropdown -3. Optionally enter a **Domain** name (for example, `company.local`). The domain is applied to all servers in the group. - -### Adding File Servers - -Click **+ Add** or click the empty state area to begin adding servers: - -1. Select **Add Manually** (CSV import is planned for a future release) -2. In the manual entry form, enter one or more server names or IP addresses: - - Type multiple entries separated by commas, or press **Enter** after each one - - For example: `fs01, fs02, fs03` -3. Set the **Port** (default: `445`) -4. Click **Add [N] file servers** -5. Review the added servers in the table — server names are editable inline -6. Click **Done** to return to the configuration screen - -The file servers table shows each server's name, connection status, and a delete button. - -### Test Connection - -After adding servers and selecting a service account: - -1. Click **Test Connection** -2. All servers are tested in parallel -3. Each server shows its status: **Connected** (green), **Failed** (red), or **Testing** (spinner) -4. A summary toast displays the results (for example, "All 3 connections successful" or "1 of 3 failed") - -:::note -Testing is optional and non-blocking — you can proceed to the next step regardless of test results. -::: - -### Connection Parameters - -Each file server in the group uses the following connection parameters: - -| Parameter | Description | Default | -| --- | --- | --- | -| **Host** | File server hostname or IP address | — | -| **Port** | SMB port | `445` | -| **Domain** | Domain name (set at the group level) | — | - -## Supported Protocols - -The connector supports SMBv2 and SMBv3. SMBv1 is not supported due to security vulnerabilities. - -## Next Steps - -After configuring servers, click **Next** to proceed to [scan setup](/docs/accessanalyzer/1_0/gettingstarted/firstscan/configuringscan), where you configure access scan options, share filtering, and scheduling. diff --git a/docs/accessanalyzer/1.0/connectors/source/cifs/filevssharelevel.md b/docs/accessanalyzer/1.0/connectors/source/cifs/filevssharelevel.md deleted file mode 100644 index e3e596a606..0000000000 --- a/docs/accessanalyzer/1.0/connectors/source/cifs/filevssharelevel.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: "File-Level vs Share-Level Permissions" -description: "Understanding file-level and share-level permission scanning" -sidebar_position: 50 ---- - -# File-Level vs Share-Level Permissions - -Windows file shares have two layers of access control: **share-level permissions** and **NTFS file-level permissions**. The effective access for a user is the most restrictive combination of both. - -## Share-Level Permissions - -Share-level permissions are set on the share itself and apply to all network access: - -- **Read** — View files and subfolders -- **Change** — Read, add, modify, and delete files -- **Full Control** — All Change permissions plus the ability to modify share permissions - -## NTFS File-Level Permissions - -NTFS permissions are set on individual files and folders and provide granular control: - -- **Read** — View file contents and attributes -- **Write** — Create files and write data -- **Modify** — Read, write, and delete -- **Full Control** — All permissions including permission changes and ownership - -## Effective Access - -The effective access for a user connecting over the network is determined by the **intersection** (most restrictive) of share-level and NTFS permissions. - -For example: -- Share permission: **Full Control** -- NTFS permission: **Read** -- Effective access: **Read** - -## Enabling File-Level Permission Scanning - -By default, Access Analyzer scans share-level permissions only. To include file-level (NTFS) permission data: - -1. During source group creation, proceed to Step 3 (scan setup) -2. Enable the **Access** scan type -3. In the access scan options, check **Include file-level permission data in scan results** - -When enabled, the connector reads the NTFS security descriptor for each file and folder in addition to the share-level ACL. This provides more detailed access path analysis but increases scan duration. - -:::note -File-level permission scanning is disabled by default because it significantly increases scan time on large file servers. Enable it when you need detailed per-file permission analysis. -::: - -## What Access Analyzer Scans - -The CIFS/SMB connector collects NTFS permissions at the file and folder level. Combined with share-level permission data, Access Analyzer reports the effective access path from user to file. diff --git a/docs/accessanalyzer/1.0/connectors/source/cifs/ntfspermissions.md b/docs/accessanalyzer/1.0/connectors/source/cifs/ntfspermissions.md deleted file mode 100644 index 6b14bc1b67..0000000000 --- a/docs/accessanalyzer/1.0/connectors/source/cifs/ntfspermissions.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: "NTFS Permission Scanning" -description: "Scanning NTFS access control lists" -sidebar_position: 30 ---- - -# NTFS Permission Scanning - -The CIFS/SMB connector reads NTFS access control lists (ACLs) on files and folders to identify who has access and what level of access they hold. - -## What Gets Collected - -| Data | Description | -| --- | --- | -| **ACL entries** | Each access control entry (ACE) on a file or folder, including the principal (user or group), access type (allow/deny), and permission level | -| **Permission types** | Read, Write, Modify, Full Control, and other standard NTFS permissions | -| **Inheritance** | Whether permissions are inherited from a parent folder or explicitly set | -| **Owner** | The owner of each file or folder | - -## How It Works - -1. The connector traverses the folder hierarchy on each share -2. For each file and folder, it reads the NTFS security descriptor -3. ACL entries are parsed and stored in the Access Analyzer database -4. Identities referenced in ACLs are matched to synced identities from IAM connectors - -## Access Path Analysis - -By combining NTFS permissions with identity data from Active Directory or Local Groups, Access Analyzer builds **access paths** that show: - -- Which users and groups have access to each file or folder -- Whether access is granted directly or through nested group membership -- Which permissions are explicitly set versus inherited diff --git a/docs/accessanalyzer/1.0/connectors/source/cifs/scandepthworkers.md b/docs/accessanalyzer/1.0/connectors/source/cifs/scandepthworkers.md deleted file mode 100644 index b83787d563..0000000000 --- a/docs/accessanalyzer/1.0/connectors/source/cifs/scandepthworkers.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: "Scan Depth and Worker Configuration" -description: "Configuring recursion depth and concurrent workers" -sidebar_position: 40 ---- - -# Scan Depth and Worker Configuration - -The CIFS/SMB connector supports configurable scan depth and concurrent worker threads to balance thoroughness with performance. These settings are configured in Step 3 (scan setup) of the Connect Source wizard when the **Access** scan option is enabled. - -## Scan Depth - -Scan depth controls how many levels of subdirectories the connector traverses within each share. - -| Setting | Description | -| --- | --- | -| **Default** | 50 levels deep | -| **Custom** | Set to any positive integer | - -The default depth of 50 covers the vast majority of file server hierarchies. Increase this value only if your environment has deeply nested folder structures that exceed 50 levels. - -:::note -Setting scan depth to a very high number does not significantly impact performance if the actual folder hierarchy is shallower — the connector stops when there are no more subdirectories to traverse. -::: - -## Worker Threads - -Worker threads control how many directories are scanned concurrently. More threads mean faster scans but higher load on the file server. - -| Setting | Description | -| --- | --- | -| **Default** | 3 concurrent workers | -| **Range** | 1 to 20 workers | - -Guidelines for choosing a worker count: - -| Workers | Use Case | -| --- | --- | -| **1–3** | Conservative scanning with minimal file server impact (default) | -| **5–10** | Balanced performance for most environments | -| **10–20** | Maximum parallelism for large file servers with high I/O capacity | - -:::warning -Increasing worker count improves scan speed but also increases load on the file server. Start with the default of 3 and increase gradually based on file server capacity and observed scan duration. -::: - -## Configuration Location - -Both settings are found in the **Access scan options** section of the scan setup step, which appears when the **Access** scan type is enabled during source group creation. - -## Related Topics - -- [Share Enumeration and Filtering](/docs/accessanalyzer/1_0/connectors/source/cifs/shareenumeration) — Controlling which shares are scanned -- [File-Level vs Share-Level Permissions](/docs/accessanalyzer/1_0/connectors/source/cifs/filevssharelevel) — Permission scanning granularity diff --git a/docs/accessanalyzer/1.0/connectors/source/cifs/shareenumeration.md b/docs/accessanalyzer/1.0/connectors/source/cifs/shareenumeration.md deleted file mode 100644 index 9bcb80a771..0000000000 --- a/docs/accessanalyzer/1.0/connectors/source/cifs/shareenumeration.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: "Share Enumeration and Filtering" -description: "Discovering and filtering network shares" -sidebar_position: 20 ---- - -# Share Enumeration and Filtering - -When scanning a CIFS/SMB source, the connector discovers all available shares on the target file server. You can include or exclude specific shares, and optionally enumerate hidden shares. - -## How Share Discovery Works - -The connector enumerates all SMB shares exposed by the file server. Each share is listed with its name and path. - -## Share Filtering - -Share filtering is configured in Step 3 (scan setup) of the Connect Source wizard when the **Access** scan option is enabled. Two filtering controls are available: - -### Include Shares - -Control which shares are scanned: - -| Mode | Behavior | -| --- | --- | -| **All shares** (default) | Scan every discovered share on the file server | -| **Custom selection** | Only scan shares you explicitly specify | - -When **Custom selection** is chosen, a text field appears where you enter share names separated by commas (for example, `share1, share2, share3`). - -### Exclude Shares - -Optionally specify shares to skip during scanning. Enter share names separated by commas in the exclude field (for example, `admin$, ipc$`). Excluded shares are never scanned, even if they match the include filter. - -## Hidden Shares - -Windows hidden shares (shares whose names end with `$`) are not enumerated by default. You can enable automatic discovery of hidden shares: - -1. In the scan setup step, check **Automatically enumerate and scan hidden shares** -2. When enabled, the connector discovers and scans hidden shares alongside regular shares -3. A predefined list of default exclusions is applied automatically - -### Excluding Hidden Shares - -When hidden share collection is enabled, an additional **Exclude Hidden Shares** field appears. Enter hidden share names to exclude from auto-enumeration (for example, `ADMIN$, C$, IPC$`). - -:::info -Filtering shares reduces scan duration and focuses results on the most relevant data repositories. Exclude administrative shares (like `ADMIN$` and `IPC$`) unless you specifically need to audit their permissions. -::: - -## Related Topics - -- [Connection Configuration](/docs/accessanalyzer/1_0/connectors/source/cifs/connectionconfig) — Setting up file server connections -- [Scan Depth and Worker Configuration](/docs/accessanalyzer/1_0/connectors/source/cifs/scandepthworkers) — Controlling scan thoroughness diff --git a/docs/accessanalyzer/1.0/connectors/source/overview.md b/docs/accessanalyzer/1.0/connectors/source/overview.md deleted file mode 100644 index 90620d8484..0000000000 --- a/docs/accessanalyzer/1.0/connectors/source/overview.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: "Source Connectors" -description: "Data source connectors for file and cloud scanning" -sidebar_position: 1 ---- - -# Source Connectors - -Source connectors scan data repositories to discover files, folders, access permissions, and content. Results are used to identify overly permissive access and detect sensitive data. - -## Available Source Connectors - -| Connector | Data Source | Operations | Credential Type | -| --- | --- | --- | --- | -| [CIFS / SMB](/docs/accessanalyzer/1_0/connectors/source/cifs/connectionconfig) | Windows file shares | Test connection, Access scan, Get object | Username / Password | -| [SharePoint Online](/docs/accessanalyzer/1_0/connectors/source/sharepointonline/connectionconfig) | SharePoint Online sites | Test connection, Access scan, Get object | Certificate | - -## Scan Types - -| Scan Type | Description | -| --- | --- | -| **Access scan** | Enumerates file structure and access permissions | -| **Sensitive data scan** | Classifies file content against detection patterns | diff --git a/docs/accessanalyzer/1.0/connectors/source/sharepointonline/_category_.json b/docs/accessanalyzer/1.0/connectors/source/sharepointonline/_category_.json deleted file mode 100644 index 4646f7123f..0000000000 --- a/docs/accessanalyzer/1.0/connectors/source/sharepointonline/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "SharePoint Online", - "position": 20, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "connectionconfig" - } -} diff --git a/docs/accessanalyzer/1.0/connectors/source/sharepointonline/connectionconfig.md b/docs/accessanalyzer/1.0/connectors/source/sharepointonline/connectionconfig.md deleted file mode 100644 index 90bd541e78..0000000000 --- a/docs/accessanalyzer/1.0/connectors/source/sharepointonline/connectionconfig.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: "Connection Configuration" -description: "Configuring SharePoint Online connection parameters" -sidebar_position: 10 ---- - -# Connection Configuration - -Configure the SharePoint Online connector to scan SharePoint sites using the Microsoft Graph API with certificate-based authentication. - -## Prerequisites - -- An Azure AD app registration with `Sites.Read.All` permission — see [SharePoint Online Requirements](/docs/accessanalyzer/1_0/requirements/connectors/sharepointonline) -- A certificate (public/private key pair) uploaded to the app registration -- Network connectivity from Access Analyzer to Microsoft Graph API (port 443) - -## Create a Service Account - -1. Navigate to **Service Accounts** in the sidebar -2. Click **Add Service Account** -3. Enter a **Name** (for example, `SharePoint Online - Graph API`) -4. Select **Certificate** as the type -5. Enter the **Client ID** (Application ID from the Azure app registration) -6. Enter the **Tenant ID** (Directory ID) -7. Upload the **Certificate** (private key `.pem` file) -8. Click **Add service account** - -## Add a SharePoint Online Source - -1. Navigate to **Configuration** > **Sources** -2. Click **Add Source** -3. Select **Data Source** as the category -4. Select **SharePoint Online** as the source type -5. Select the certificate-based service account created above -6. Click **Test Connection** to verify Graph API connectivity -7. After a successful test, click **Create Source** - -## Test Connection - -The test connection validates: - -- Certificate authentication with the Microsoft identity platform -- Graph API access with the configured permissions -- Ability to enumerate SharePoint sites diff --git a/docs/accessanalyzer/1.0/connectors/source/sharepointonline/permissionsharinglinks.md b/docs/accessanalyzer/1.0/connectors/source/sharepointonline/permissionsharinglinks.md deleted file mode 100644 index 18a311c439..0000000000 --- a/docs/accessanalyzer/1.0/connectors/source/sharepointonline/permissionsharinglinks.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: "Permission and Sharing Link Analysis" -description: "Analyzing SharePoint permissions and external sharing links" -sidebar_position: 30 ---- - -# Permission and Sharing Link Analysis - -The SharePoint Online connector collects permission data from SharePoint sites to identify who has access to documents and whether content is shared externally. - -## What Gets Collected - -| Data | Description | -| --- | --- | -| **Site permissions** | Users and groups with access to the site, including permission levels (Full Control, Edit, Read) | -| **Library permissions** | Custom permissions set at the document library level | -| **Item-level permissions** | Unique permissions on individual files or folders (broken inheritance) | -| **Sharing links** | Anonymous links, organization-wide links, and people-specific sharing links | - -## Sharing Link Types - -| Link Type | Description | Risk Level | -| --- | --- | --- | -| **Anyone** | Anonymous access — no authentication required | High | -| **Organization** | Anyone in the organization can access | Medium | -| **Specific people** | Only named users can access | Low | - -## How It Helps - -Permission and sharing link analysis enables you to: - -- Identify documents shared externally via anonymous links -- Find overly permissive site-level access -- Detect broken permission inheritance on sensitive documents -- Review sharing link expiration and access levels diff --git a/docs/accessanalyzer/1.0/connectors/source/sharepointonline/scanningspecificsites.md b/docs/accessanalyzer/1.0/connectors/source/sharepointonline/scanningspecificsites.md deleted file mode 100644 index e4203c5679..0000000000 --- a/docs/accessanalyzer/1.0/connectors/source/sharepointonline/scanningspecificsites.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: "Scanning Specific Sites" -description: "Targeting specific SharePoint sites for scanning" -sidebar_position: 40 ---- - -# Scanning Specific Sites - -By default, the SharePoint Online connector scans all sites accessible to the configured app registration. You can narrow the scope by including or excluding specific sites. - -## Configuring Site Filters - -Site filtering is configured during scan creation in the **Configure Details** step: - -1. Navigate to **Configuration** > **Scans** -2. Create a new scan for the SharePoint Online source -3. In the **Configure Details** step, set site include or exclude filters - -## Filter Options - -| Option | Behavior | -| --- | --- | -| **Include specific sites** | Only scan the listed sites | -| **Exclude specific sites** | Scan all sites except those listed | - -## Use Cases - -- **Compliance scanning** — Scan only sites that contain regulated data (HR, Finance, Legal) -- **Incremental rollout** — Start with a subset of sites and expand over time -- **Performance** — Reduce scan duration by excluding large, low-priority sites diff --git a/docs/accessanalyzer/1.0/connectors/source/sharepointonline/sitelibraryenum.md b/docs/accessanalyzer/1.0/connectors/source/sharepointonline/sitelibraryenum.md deleted file mode 100644 index 62a46f11d3..0000000000 --- a/docs/accessanalyzer/1.0/connectors/source/sharepointonline/sitelibraryenum.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: "Site and Library Enumeration" -description: "Discovering SharePoint sites and document libraries" -sidebar_position: 20 ---- - -# Site and Library Enumeration - -The SharePoint Online connector discovers SharePoint sites, document libraries, and their contents through the Microsoft Graph API. - -## What Gets Discovered - -| Object Type | Description | -| --- | --- | -| **Sites** | All SharePoint Online sites accessible to the app registration | -| **Document libraries** | Libraries within each site containing files and folders | -| **Files and folders** | Individual items with metadata (name, size, modified date, author) | - -## How It Works - -1. The connector authenticates with the Graph API using the configured certificate -2. Sites are enumerated based on the app registration's permissions (`Sites.Read.All`) -3. For each site, document libraries are discovered -4. Files and folders within each library are traversed and cataloged -5. Results are sent to the Core API for storage and analysis - -## Site Filtering - -You can control which sites are scanned using include/exclude filters. See [Scanning Specific Sites](/docs/accessanalyzer/1_0/connectors/source/sharepointonline/scanningspecificsites) for details. diff --git a/docs/accessanalyzer/1.0/dashboards/_category_.json b/docs/accessanalyzer/1.0/dashboards/_category_.json deleted file mode 100644 index 4795b98214..0000000000 --- a/docs/accessanalyzer/1.0/dashboards/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Dashboards and Reports", - "position": 80, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/dashboards/activedirectory.md b/docs/accessanalyzer/1.0/dashboards/activedirectory.md deleted file mode 100644 index 0a72e8f46e..0000000000 --- a/docs/accessanalyzer/1.0/dashboards/activedirectory.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Active Directory Dashboard" -description: "Active Directory identity and access insights" -sidebar_position: 20 -draft: true ---- - -# Active Directory Dashboard diff --git a/docs/accessanalyzer/1.0/dashboards/copilotreadiness.md b/docs/accessanalyzer/1.0/dashboards/copilotreadiness.md deleted file mode 100644 index ea7b3647a0..0000000000 --- a/docs/accessanalyzer/1.0/dashboards/copilotreadiness.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Copilot Readiness Dashboard" -description: "Microsoft 365 Copilot readiness assessment" -sidebar_position: 50 -draft: true ---- - -# Copilot Readiness Dashboard diff --git a/docs/accessanalyzer/1.0/dashboards/datasecurity.md b/docs/accessanalyzer/1.0/dashboards/datasecurity.md deleted file mode 100644 index a9db5d2e47..0000000000 --- a/docs/accessanalyzer/1.0/dashboards/datasecurity.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Data Security Dashboard" -description: "Data security posture and risk summary" -sidebar_position: 40 -draft: true ---- - -# Data Security Dashboard diff --git a/docs/accessanalyzer/1.0/dashboards/entraid.md b/docs/accessanalyzer/1.0/dashboards/entraid.md deleted file mode 100644 index c2f2ebf0c2..0000000000 --- a/docs/accessanalyzer/1.0/dashboards/entraid.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Entra ID Dashboard" -description: "Entra ID identity and access insights" -sidebar_position: 30 -draft: true ---- - -# Entra ID Dashboard diff --git a/docs/accessanalyzer/1.0/dashboards/metabase/_category_.json b/docs/accessanalyzer/1.0/dashboards/metabase/_category_.json deleted file mode 100644 index af130ea1f5..0000000000 --- a/docs/accessanalyzer/1.0/dashboards/metabase/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Metabase Reports", - "position": 60, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "accessingreports" - } -} diff --git a/docs/accessanalyzer/1.0/dashboards/metabase/accessingreports.md b/docs/accessanalyzer/1.0/dashboards/metabase/accessingreports.md deleted file mode 100644 index c9919abbcc..0000000000 --- a/docs/accessanalyzer/1.0/dashboards/metabase/accessingreports.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: "Accessing Embedded Reports" -description: "Using Metabase embedded reports in Access Analyzer" -sidebar_position: 10 ---- - -# Accessing Embedded Reports - -Access Analyzer embeds Metabase reports directly into the application interface. You can view, filter, and interact with reports without leaving the platform. - -## Opening a Report - -1. Navigate to the **Dashboards** section in the left navigation menu. -2. Select a dashboard from the list of available dashboards (for example, **Data Security Dashboard**). -3. The embedded Metabase report loads within the Access Analyzer interface. - -## Authentication - -Report access uses JWT-based single sign-on between the Access Analyzer Core API and Metabase. No separate Metabase credentials are required. Your Access Analyzer user permissions determine which dashboards and data you can view. - -## Interacting with Reports - -Once a report is loaded, you can: - -- **Apply filters** — Use the filter controls at the top of the dashboard to narrow results by date range, data source, compliance framework, or data type. -- **Drill down** — Click on chart elements or table rows to view detailed breakdowns of the underlying data. -- **Adjust time ranges** — Modify the reporting period to compare findings across different scan windows. - -:::note -Dashboards display data from the most recent completed scans. If you do not see expected results, verify that a [sensitive data scan](/docs/accessanalyzer/1_0/sensitivedatadiscovery/runningscan) has been run against the target data sources. -::: - -## Next Steps - -- [Save reports](/docs/accessanalyzer/1_0/dashboards/metabase/savedreports) for repeated access -- [Export report data](/docs/accessanalyzer/1_0/dashboards/metabase/exportingdata) for external use diff --git a/docs/accessanalyzer/1.0/dashboards/metabase/exportingdata.md b/docs/accessanalyzer/1.0/dashboards/metabase/exportingdata.md deleted file mode 100644 index 9b8531c8e7..0000000000 --- a/docs/accessanalyzer/1.0/dashboards/metabase/exportingdata.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: "Exporting Report Data" -description: "Exporting report data for external use" -sidebar_position: 30 ---- - -# Exporting Report Data - -Access Analyzer allows you to export dashboard data from embedded Metabase reports for use in external tools, compliance documentation, or offline analysis. - -## Exporting from a Dashboard - -To export data from a dashboard or saved report: - -1. Open the desired dashboard or [saved report](/docs/accessanalyzer/1_0/dashboards/metabase/savedreports). -2. Apply any filters to scope the data to your requirements. -3. Click the **Export** button in the dashboard toolbar. -4. Select the export format: - - **CSV** — Comma-separated values for use in spreadsheets and data processing tools - - **JSON** — Structured data format for programmatic consumption - - **PDF** — Formatted report suitable for distribution and compliance documentation -5. Click **Download** to save the exported file. - -## Export Scope - -The exported data reflects the current dashboard view, including all applied filters. Only the data visible in the current report configuration is included in the export. - -| Export Format | Best For | -| --- | --- | -| CSV | Importing into Excel, Google Sheets, or data analysis tools | -| JSON | Integration with APIs, scripts, or automated reporting pipelines | -| PDF | Sharing with stakeholders, auditors, or compliance teams | - -:::warning -Exported reports may contain sensitive data findings. Handle exported files according to your organization's data handling and classification policies. -::: - -## Next Steps - -- [Configure saved reports](/docs/accessanalyzer/1_0/dashboards/metabase/savedreports) to streamline recurring exports -- [Review sensitive data scan results](/docs/accessanalyzer/1_0/sensitivedatadiscovery/reviewingresults/matchcounts) for detailed match-level data diff --git a/docs/accessanalyzer/1.0/dashboards/metabase/savedreports.md b/docs/accessanalyzer/1.0/dashboards/metabase/savedreports.md deleted file mode 100644 index 8d565d14fe..0000000000 --- a/docs/accessanalyzer/1.0/dashboards/metabase/savedreports.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: "Saved Reports" -description: "Creating and managing saved reports" -sidebar_position: 20 ---- - -# Saved Reports - -The saved reports feature allows you to preserve specific dashboard configurations, including applied filters and selected parameters, for quick access in future sessions. - -## Saving a Report - -1. Open a dashboard and apply the desired filters (date range, data source, compliance framework, or other parameters). -2. Click the **Save Report** button in the dashboard toolbar. -3. Enter a **Name** for the saved report. -4. Optionally add a **Description** to document the report's purpose. -5. Click **Save**. - -The saved report appears in your **Saved Reports** list for future access. - -## Managing Saved Reports - -To view and manage your saved reports: - -1. Navigate to **Dashboards** > **Saved Reports**. -2. The list displays all saved reports with their name, description, and creation date. -3. Click a saved report to load it with the preserved filter configuration. -4. To update a saved report, modify the filters and click **Save Report** again, then choose to overwrite the existing report. -5. To delete a saved report, select it and click **Delete**. - -:::note -Saved reports retain the filter configuration, not a static snapshot of the data. When you open a saved report, the dashboard applies the saved filters against the latest scan data, ensuring results are always current. -::: - -## Next Steps - -- [Export report data](/docs/accessanalyzer/1_0/dashboards/metabase/exportingdata) from a saved report configuration -- [Return to the dashboards overview](/docs/accessanalyzer/1_0/dashboards/overview) to explore other reporting options diff --git a/docs/accessanalyzer/1.0/dashboards/overview.md b/docs/accessanalyzer/1.0/dashboards/overview.md deleted file mode 100644 index d996ab6f5f..0000000000 --- a/docs/accessanalyzer/1.0/dashboards/overview.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: "Dashboards and Reports" -description: "Overview of dashboards, metrics, and reporting capabilities" -sidebar_position: 10 ---- - -# Dashboards and Reports - -Netwrix Access Analyzer provides embedded analytics dashboards powered by Metabase. The **Dashboards** section gives you visual insight into your organization's data security posture, sensitive data findings, and access risk summaries. - -## Embedded Analytics - -Access Analyzer integrates Metabase as an embedded reporting engine with an airgap premium token. Authentication is handled automatically through JWT-based single sign-on from the Core API to Metabase, so users access dashboards directly from within the Access Analyzer interface without separate login credentials. - -## Available Dashboards - -Pre-built dashboards are visible in the **Dashboards** section of the application. The primary dashboard is the **Data Security Dashboard**, which provides: - -- **Sensitive data findings summary** — Aggregated match counts across all scanned sources -- **Risk summary** — High-level view of data exposure organized by severity and compliance framework -- **Trend analysis** — Changes in sensitive data findings over time - -## Reporting Capabilities - -| Feature | Description | -| --- | --- | -| [Accessing Reports](/docs/accessanalyzer/1_0/dashboards/metabase/accessingreports) | View and interact with embedded Metabase reports | -| [Saved Reports](/docs/accessanalyzer/1_0/dashboards/metabase/savedreports) | Save report configurations for repeated use | -| [Exporting Data](/docs/accessanalyzer/1_0/dashboards/metabase/exportingdata) | Export dashboard data for external analysis or compliance documentation | - -:::note -Dashboard content updates automatically as new scan results become available. Run a [sensitive data scan](/docs/accessanalyzer/1_0/sensitivedatadiscovery/runningscan) to populate dashboards with the latest findings. -::: diff --git a/docs/accessanalyzer/1.0/gettingstarted/_category_.json b/docs/accessanalyzer/1.0/gettingstarted/_category_.json deleted file mode 100644 index c8341a5bc3..0000000000 --- a/docs/accessanalyzer/1.0/gettingstarted/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Getting Started", - "position": 20, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/gettingstarted/dashboardwalkthrough.md b/docs/accessanalyzer/1.0/gettingstarted/dashboardwalkthrough.md deleted file mode 100644 index 1416847ba0..0000000000 --- a/docs/accessanalyzer/1.0/gettingstarted/dashboardwalkthrough.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: "Overview Dashboard Walkthrough" -description: "Navigating the main dashboard and key metrics" -sidebar_position: 30 ---- - -# Overview Dashboard Walkthrough - -After signing in, Access Analyzer displays the main interface with a sidebar navigation menu and a central content area. This page introduces the key areas of the application. - -## Sidebar Navigation - -The sidebar provides access to all major sections: - -| Section | Description | -| --- | --- | -| **Dashboards** | Pre-built Metabase dashboards for data security posture and identity analysis | -| **Reports** | Access, content, activity, and sensitive data reports | -| **Configuration** | Sources, scans, scan executions, and sensitive data settings | -| **Service Accounts** | Manage credentials used to connect to data sources | -| **Administration** | User management and system logs (administrator only) | -| **Settings** | Application-wide settings | - -## Dashboards - -The **Dashboards** section contains embedded Metabase dashboards that provide a visual summary of your environment: - -- **Data Security Dashboard** — Overview of sensitive data findings, file statistics, and framework coverage -- Additional dashboards become available as you add data sources and run scans - -Dashboards update automatically after each scan execution. - -## Configuration Section - -The **Configuration** section is where most of the day-to-day work happens: - -- **Sources** — Add and manage the data sources and identity providers Access Analyzer connects to -- **Scans** — Create, schedule, and manage access scans and sensitive data scans -- **Scan Executions** — View the history of scan runs, including status, duration, and progress -- **Sensitive Data** — Configure the detection frameworks and patterns used during sensitive data scans - -## Next Steps - -- [Your First Scan](/docs/accessanalyzer/1_0/gettingstarted/firstscan/overview) — Follow the step-by-step guide to add a source, configure a scan, and review results diff --git a/docs/accessanalyzer/1.0/gettingstarted/firstlogin.md b/docs/accessanalyzer/1.0/gettingstarted/firstlogin.md deleted file mode 100644 index defd35ef14..0000000000 --- a/docs/accessanalyzer/1.0/gettingstarted/firstlogin.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: "First Login and Admin Setup" -description: "Initial administrator account creation and login" -sidebar_position: 20 ---- - -# First Login and Admin Setup - -After installing Access Analyzer, the first step is to access the web interface, create your administrator account, and sign in. - -## Access the Application - -Open a browser and navigate to: - -``` -https:// -``` - -Replace `` with the IP address or hostname of the VM where Access Analyzer is installed. - -:::note -Access Analyzer uses a self-signed TLS certificate by default. Your browser will display a security warning — accept the warning to proceed to the login page. To use a trusted certificate, see [SSL / TLS Configuration](/docs/accessanalyzer/1_0/install/ssl). -::: - -## Create the Administrator Account - -The first user to create an account is automatically assigned the **Administrator** role. - -1. On the login page, click **Create Account** -2. Enter the following: - - **Full Name** — Your display name - - **Email Address** — Used as your login username - - **Password** — Must meet complexity requirements - - **Confirm Password** — Re-enter the password -3. Click **Create Account** - -:::warning -The first account created receives full administrator privileges. Ensure this account is created by an authorized administrator. -::: - -## Sign In - -1. Enter the email address and password you used during account creation -2. Click **Sign In** - -You are now signed in with full administrator access. - -## Next Steps - -- [Overview Dashboard Walkthrough](/docs/accessanalyzer/1_0/gettingstarted/dashboardwalkthrough) — Explore the main interface -- [Your First Scan](/docs/accessanalyzer/1_0/gettingstarted/firstscan/overview) — Add a data source and run your first scan -- [Users and Roles](/docs/accessanalyzer/1_0/admin/users/overview) — Create additional user accounts diff --git a/docs/accessanalyzer/1.0/gettingstarted/firstscan/_category_.json b/docs/accessanalyzer/1.0/gettingstarted/firstscan/_category_.json deleted file mode 100644 index d8feb251f3..0000000000 --- a/docs/accessanalyzer/1.0/gettingstarted/firstscan/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Your First Scan", - "position": 30, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/gettingstarted/firstscan/addingsource.md b/docs/accessanalyzer/1.0/gettingstarted/firstscan/addingsource.md deleted file mode 100644 index b37b596118..0000000000 --- a/docs/accessanalyzer/1.0/gettingstarted/firstscan/addingsource.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: "Adding a Data Source" -description: "Connect a data source using the Connect Source wizard" -sidebar_position: 20 ---- - -# Adding a Data Source - -Before scanning, you need to connect a data source to Access Analyzer. The **Connect Source** wizard guides you through a 3-step process: select the source type, configure the connection, and set up a scan. - -## Open the Connect Source Wizard - -1. Navigate to **Configuration** > **Sources** in the sidebar -2. Click **Connect Source** to open the wizard drawer - -## Step 1 — Select Source Type - -Choose the type of data source to connect: - -| Source Type | Category | Description | -| --- | --- | --- | -| **Active Directory** | IAM | Domain controllers, users, groups, and permissions | -| **Entra ID** | IAM | Azure AD tenant with users, groups, and roles | -| **File Server** | Data Source | Windows file shares (CIFS/SMB) | -| **SharePoint Online** | Data Source | SharePoint sites and document libraries | - -Select a source type card and click **Next**. - -## Step 2 — Configure the Source - -Configuration varies by source type. For this getting started guide, we'll walk through the **File Server** example — the most common first source. - -### File Server Configuration - -1. Enter a **Source Group Name** (for example, `Finance File Servers`) -2. Select or create a **Service Account**: - - Click **+ Create New Account** to add credentials inline - - Select **Username/Password** and enter the username and password for an account with read access to the target file servers - - Or select an existing service account from the dropdown -3. Optionally enter a **Domain** name (for example, `company.local`) - -### Add File Servers - -1. Click **+ Add** or the empty state area -2. Select **Add Manually** -3. Enter one or more server names or IP addresses, separated by commas or pressing **Enter** after each -4. Set the **Port** (default: `445`) -5. Click **Add file servers**, then click **Done** - -### Test Connection (Optional) - -Click **Test Connection** to verify connectivity to all servers. Each server shows its connection status (Connected, Failed, or Testing). Testing is non-blocking — you can proceed regardless of results. - -:::note -If a connection test fails, verify network connectivity on port 445 and that the service account has read access to the target shares. -::: - -Click **Next** to proceed to scan setup. - -### Other Source Types - -For detailed configuration instructions for each source type, see: - -- [Active Directory](/docs/accessanalyzer/1_0/connectors/iam/activedirectory/connectionsetup) — Domain controller configuration -- [Entra ID](/docs/accessanalyzer/1_0/connectors/iam/entraid/appregistration) — Azure AD app registration and tenant setup -- [SharePoint Online](/docs/accessanalyzer/1_0/connectors/source/sharepointonline/connectionconfig) — Site collection configuration - -## Next Step - -[Configuring a Scan](/docs/accessanalyzer/1_0/gettingstarted/firstscan/configuringscan) — Set up scanning options and schedule your first scan. diff --git a/docs/accessanalyzer/1.0/gettingstarted/firstscan/configuringscan.md b/docs/accessanalyzer/1.0/gettingstarted/firstscan/configuringscan.md deleted file mode 100644 index 14df574f12..0000000000 --- a/docs/accessanalyzer/1.0/gettingstarted/firstscan/configuringscan.md +++ /dev/null @@ -1,94 +0,0 @@ ---- -title: "Configuring a Scan" -description: "Set up scanning options and schedule in the Connect Source wizard" -sidebar_position: 30 ---- - -# Configuring a Scan - -Step 3 of the Connect Source wizard configures what to scan and when. The available options depend on the source type selected in Step 1. - -## Available Scanning Options - -Select which scan types to enable for the source group. Available options vary by source type: - -### File Server Scan Types - -| Scan Type | Description | -| --- | --- | -| **Access** | Scan file server permissions and access controls | -| **Sensitive Data** | Scan file contents for sensitive data patterns (PII, credentials, PHI, financial data) | - -At least one scan type must be enabled to proceed. - -:::info -When the **Access** scan is enabled, a **Local Users and Groups** scan is also created automatically to collect local account data from each file server. This happens behind the scenes and does not require additional configuration. -::: - -### Entra ID Scan Types - -| Scan Type | Description | -| --- | --- | -| **Users, Groups and Roles** | Synchronize users, groups, and directory roles from the Azure AD tenant | - -This scan type is always enabled and cannot be disabled. Additional sync options (such as **Sync Sensitivity Labels**) may appear below the toggle. - -### Active Directory Scan Types - -| Scan Type | Description | -| --- | --- | -| **Active Directory Inventory** | Synchronize users, groups, OUs, and permissions from domain controllers | - -## Access Scan Options (File Server) - -When the **Access** scan type is enabled for a File Server source, additional configuration options appear: - -### Share Selection - -- **Include Shares** — Choose **All shares** (default) or **Custom selection** to specify specific share names -- **Exclude Shares** — Optionally list shares to skip (for example, `admin$, ipc$`) - -### Scan Depth - -- Maximum folder depth to scan (default: **50**) -- Controls how many levels of subdirectories the connector traverses - -### File-Level Permissions - -- Check **Include file-level permission data in scan results** to collect NTFS ACLs on individual files -- Disabled by default — increases scan duration on large file servers - -### Hidden Shares - -- Check **Automatically enumerate and scan hidden shares** to discover shares ending with `$` -- When enabled, an **Exclude Hidden Shares** field appears to specify hidden shares to skip (for example, `ADMIN$, C$, IPC$`) - -### Worker Threads - -- Number of concurrent workers for parallel directory enumeration (default: **3**) -- Higher values scan faster but increase load on the file server - -For detailed information about each option, see the [CIFS connector documentation](/docs/accessanalyzer/1_0/connectors/source/cifs/connectionconfig). - -## Scan Start Time - -Choose when to run the first scan: - -| Option | Description | -| --- | --- | -| **Run scan now** | Execute immediately after setup completes (default) | -| **Run scan at** | Schedule for a specific date and time — must be in the future | -| **Advanced scheduling** | Configure a recurring schedule using a cron expression | - -## Complete Setup - -Click **Complete Setup** to create the source group with all configured sources and scans. On success: - -1. The source group and all sources are created -2. Scans are created according to your configuration -3. The wizard closes and the sources list refreshes -4. Scans execute according to the selected schedule - -## Next Step - -[Running and Monitoring a Scan](/docs/accessanalyzer/1_0/gettingstarted/firstscan/runningscan) — Track scan progress and review results. diff --git a/docs/accessanalyzer/1.0/gettingstarted/firstscan/overview.md b/docs/accessanalyzer/1.0/gettingstarted/firstscan/overview.md deleted file mode 100644 index 9d968a68bd..0000000000 --- a/docs/accessanalyzer/1.0/gettingstarted/firstscan/overview.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: "Your First Scan" -description: "Step-by-step guide to running your first scan" -sidebar_position: 10 ---- - -# Your First Scan - -This guide walks you through the complete workflow of adding a data source, creating a scan, running it, and reviewing the results. The example uses a CIFS/SMB file share, but the workflow is similar for all source types. - -## Workflow Summary - -| Step | Description | Page | -| --- | --- | --- | -| 1 | Create a service account with credentials for your data source | [Adding a Data Source](/docs/accessanalyzer/1_0/gettingstarted/firstscan/addingsource) | -| 2 | Add a data source and test the connection | [Adding a Data Source](/docs/accessanalyzer/1_0/gettingstarted/firstscan/addingsource) | -| 3 | Create a scan and select scan type | [Configuring a Scan](/docs/accessanalyzer/1_0/gettingstarted/firstscan/configuringscan) | -| 4 | Run the scan and monitor progress | [Running and Monitoring a Scan](/docs/accessanalyzer/1_0/gettingstarted/firstscan/runningscan) | -| 5 | Review findings in dashboards and scan results | [Viewing Results](/docs/accessanalyzer/1_0/gettingstarted/firstscan/viewingresults) | - -## Prerequisites - -Before starting, ensure you have: - -- Signed in as an administrator — see [First Login](/docs/accessanalyzer/1_0/gettingstarted/firstlogin) -- A data source available on the network (for example, a CIFS/SMB file share) -- Credentials with read access to the data source -- Network connectivity from the Access Analyzer VM to the data source (for example, port 445 for SMB) diff --git a/docs/accessanalyzer/1.0/gettingstarted/firstscan/runningscan.md b/docs/accessanalyzer/1.0/gettingstarted/firstscan/runningscan.md deleted file mode 100644 index 9d9f001798..0000000000 --- a/docs/accessanalyzer/1.0/gettingstarted/firstscan/runningscan.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: "Running and Monitoring a Scan" -description: "Execute a scan and monitor its progress" -sidebar_position: 40 ---- - -# Running and Monitoring a Scan - -Once a scan is created, you can run it immediately or let it execute on its configured schedule. - -## Running a Scan - -There are two ways to start a scan: - -- **From the scan creation wizard** — Select **Create & Run Immediately** in the final step -- **From the Scans list** — Navigate to **Configuration** > **Scans**, click the menu button on the scan row, and select **Run** - -## Monitoring Scan Progress - -Navigate to **Configuration** > **Scan Executions** to view all scan runs. - -Each execution displays: - -| Field | Description | -| --- | --- | -| **Scan Name** | The name of the scan | -| **Scan Type** | Access or Sensitive Data | -| **Source** | The data source being scanned | -| **Status** | Running, Completed, Failed, or Paused | -| **Start Time** | When the scan execution began | -| **Duration** | Elapsed time since the scan started | - -You can filter executions by scan type, source, status, date range, and duration. - -## Scan Execution Actions - -While a scan is running, the following actions are available from the execution row menu: - -| Action | Description | -| --- | --- | -| **Stop** | Cancel the running scan | -| **Pause** | Pause the scan (CIFS/SMB sources only) | -| **Resume** | Resume a paused scan (CIFS/SMB sources only) | - -## Scan Statuses - -| Status | Meaning | -| --- | --- | -| **Running** | Scan is actively processing | -| **Completed** | Scan finished successfully | -| **Failed** | Scan encountered an error — check the execution logs | -| **Paused** | Scan has been paused and can be resumed | - -## Next Step - -[Viewing Results](/docs/accessanalyzer/1_0/gettingstarted/firstscan/viewingresults) — Review the findings from your completed scan. diff --git a/docs/accessanalyzer/1.0/gettingstarted/firstscan/viewingresults.md b/docs/accessanalyzer/1.0/gettingstarted/firstscan/viewingresults.md deleted file mode 100644 index f41a7de471..0000000000 --- a/docs/accessanalyzer/1.0/gettingstarted/firstscan/viewingresults.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: "Viewing Results" -description: "Review scan results and findings" -sidebar_position: 50 ---- - -# Viewing Results - -After a scan completes, results are available in the dashboards and reports sections. - -## Data Security Dashboard - -Navigate to **Dashboards** > **Data Security Dashboard** to view a summary of findings from your scans. The dashboard provides visualizations for: - -- Sensitive data findings by type and compliance framework -- File and data statistics -- Data exposure and risk indicators - -The dashboard updates automatically after each scan execution completes. - -## Scan Execution Details - -For per-scan results, navigate to **Configuration** > **Scan Executions**: - -1. Find the completed scan execution in the list -2. Click on the execution to view detailed results -3. Review the findings, including: - - Files and folders analyzed - - Permissions and access paths discovered - - Sensitive data matches (for sensitive data scans) - -## Reports - -Access Analyzer provides several report categories accessible from the sidebar: - -| Report Type | Description | -| --- | --- | -| **Access Reports** | Permission analysis and access path details | -| **Content Reports** | File and folder inventory statistics | -| **Sensitive Data Reports** | Sensitive data findings by category and compliance framework | - -## What's Next - -Now that you have completed your first scan and reviewed the results, consider these next steps: - -- **Add more data sources** — Connect additional file shares, SharePoint sites, or identity providers. See [Connectors](/docs/accessanalyzer/1_0/connectors/overview). -- **Configure sensitive data detection** — Customize detection patterns and taxonomy groups. See [Sensitive Data Discovery](/docs/accessanalyzer/1_0/sensitivedatadiscovery/overview). -- **Schedule recurring scans** — Set up automated scan schedules to maintain continuous visibility. See [Scans](/docs/accessanalyzer/1_0/admin/scans/overview). -- **Create additional users** — Add team members with appropriate roles. See [Users and Roles](/docs/accessanalyzer/1_0/admin/users/overview). diff --git a/docs/accessanalyzer/1.0/gettingstarted/overview.md b/docs/accessanalyzer/1.0/gettingstarted/overview.md deleted file mode 100644 index bb9c6c66f8..0000000000 --- a/docs/accessanalyzer/1.0/gettingstarted/overview.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: "Getting Started" -description: "Get up and running with Access Analyzer" -sidebar_position: 10 ---- - -# Getting Started - -This section walks you through the initial setup steps after installing Access Analyzer, from your first login to running your first scan and reviewing results. - -## Getting Started Steps - -| Step | Description | Page | -| --- | --- | --- | -| 1 | Sign in and create your administrator account | [First Login and Admin Setup](/docs/accessanalyzer/1_0/gettingstarted/firstlogin) | -| 2 | Explore the main dashboard and navigation | [Overview Dashboard Walkthrough](/docs/accessanalyzer/1_0/gettingstarted/dashboardwalkthrough) | -| 3 | Add a data source, configure a scan, and view results | [Your First Scan](/docs/accessanalyzer/1_0/gettingstarted/firstscan/overview) | - -## Prerequisites - -Before starting this guide, ensure you have: - -- Completed the [installation](/docs/accessanalyzer/1_0/install/overview) of Access Analyzer -- Verified that all services are healthy — see [Post-Installation Validation](/docs/accessanalyzer/1_0/install/postinstall) -- Network connectivity from the Access Analyzer VM to the data sources you plan to scan -- Credentials (service account) for the data sources you want to connect diff --git a/docs/accessanalyzer/1.0/index.md b/docs/accessanalyzer/1.0/index.md index ee95583019..854bbb7dbe 100644 --- a/docs/accessanalyzer/1.0/index.md +++ b/docs/accessanalyzer/1.0/index.md @@ -1,30 +1,20 @@ --- title: "Netwrix Access Analyzer Documentation" -description: "Netwrix Access Analyzer 1.0 product documentation - installation, administration, connectors, and sensitive data discovery" +description: "Netwrix Access Analyzer 1.0 product documentation - on-premises DSPM platform for data security and access analysis" sidebar_position: 1 --- # Netwrix Access Analyzer Documentation -Netwrix Access Analyzer is a cloud-native Data Security Posture Management (DSPM) platform that helps organizations discover, classify, and monitor sensitive data across enterprise systems and cloud storage. It provides comprehensive visibility into data access patterns, identifies compliance risks, and enables data governance at scale. +Netwrix Access Analyzer is an on-premises Data Security Posture Management (DSPM) platform that helps organizations discover, classify, and monitor sensitive data across enterprise file systems. Deployed entirely within your own infrastructure, it provides comprehensive visibility into data access patterns, identifies compliance risks, and enables data governance — without sending data to the cloud. ## Key Capabilities -- **Data Source Scanning** — Connect to CIFS/SMB file shares, SharePoint Online, and more to discover and analyze data +- **Data Source Scanning** — Connect to CIFS/SMB file shares and other on-premises data repositories to discover and analyze data - **Sensitive Data Discovery** — Detect sensitive data using built-in and custom regex patterns with taxonomy-based classification - **Identity and Access Management** — Sync users and groups from Active Directory and Entra ID to analyze permission paths -- **Activity Monitoring** — Track file access and user activity via Netwrix Activity Monitor integration - **Dashboards and Reporting** — Visualize security posture with built-in dashboards and embedded Metabase reports ## Documentation Sections -- [Overview](overview/overview) — Architecture, components, and key concepts -- [Getting Started](gettingstarted/overview) — First login, dashboard walkthrough, and your first scan -- [Requirements](requirements/overview) — System, database, and connector prerequisites -- [Installation](install/overview) — Kubernetes deployment, infrastructure setup, and database initialization -- [Administration](admin/overview) — User management, sources, scans, and application settings -- [Connectors](connectors/overview) — IAM and source connector configuration -- [Sensitive Data Discovery](sensitivedatadiscovery/overview) — Patterns, taxonomy, classification, and scan results -- [Dashboards and Reports](dashboards/overview) — Built-in dashboards and Metabase reporting -- [Activity Monitoring](activitymonitoring/overview) — Syslog integration with Netwrix Activity Monitor -- [Monitoring and Troubleshooting](troubleshooting/overview) — Health checks, observability, and common issues +- [Overview](overview/overview) — Introduction to the product, key concepts, requirements, and installation diff --git a/docs/accessanalyzer/1.0/overview/architecture.md b/docs/accessanalyzer/1.0/overview/architecture.md deleted file mode 100644 index 56014309b5..0000000000 --- a/docs/accessanalyzer/1.0/overview/architecture.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -title: "Architecture Overview" -description: "Core components and how they work together" -sidebar_position: 20 ---- - -# Architecture Overview - -Access Analyzer runs as a set of containerized services on a single-node Kubernetes cluster (K3s), managed by ArgoCD for automated deployment and updates. - -## Component Architecture - -| Component | Technology | Purpose | -| --- | --- | --- | -| **Core API** | Ruby on Rails 8 | Business logic, REST API, session management | -| **Web Application** | React 18, TypeScript | User interface and dashboards | -| **Connector API** | Go | Manages connector execution as Kubernetes Jobs | -| **PostgreSQL** | v14.18 | Primary relational database for configuration and scan metadata | -| **ClickHouse** | v25.8.13 | Analytics database for scan results, logs, and traces | -| **Redis** | v8.4.0 | Session storage, job queues, and caching | -| **Metabase** | Embedded (airgap) | Dashboard and reporting engine | -| **Traefik** | Ingress controller | TLS termination and request routing | -| **ArgoCD** | v3.2.0 | GitOps-based application lifecycle management | -| **K3s** | v1.33.4 | Lightweight Kubernetes distribution | -| **OpenTelemetry** | Collector | Observability data pipeline (traces and logs) | -| **Prometheus** | v3.8.0 | Metrics collection and alerting | - -## Communication Flow - -Access Analyzer operates in three phases: - -### Phase 1 — Installation - -The installer deploys K3s and ArgoCD on the target VM. ArgoCD connects to the Netwrix OCI registry to pull application Helm charts. - -### Phase 2 — Application Sync - -ArgoCD deploys applications in ordered sync waves: - -| Wave | Components | -| --- | --- | -| **Wave -5** | Secrets initialization (auto-generated database passwords, API keys) | -| **Wave 1** | Infrastructure: PostgreSQL, ClickHouse, Redis, OpenTelemetry, Prometheus, Traefik | -| **Wave 2** | Core services: Core API, Web Application, Connector API, Metabase | -| **Wave 3** | Functions and database seeds | - -### Phase 3 — Ongoing Operations - -- **Traefik** routes incoming requests: `/api/` → Core API, `/metabase` → Metabase, `/` → Web Application -- **Core API** processes user requests and schedules scan jobs via Sidekiq (Redis-backed job queues) -- **Connector API** executes connectors as Kubernetes Jobs to scan data sources -- **Metabase** provides embedded dashboards with JWT-based single sign-on from Core API -- **ArgoCD** continuously monitors the OCI registry for updates and applies changes automatically - -## Namespace Layout - -| Namespace | Contents | -| --- | --- | -| `access-analyzer` | All application workloads (Core API, databases, connectors, Metabase, observability) | -| `argocd` | ArgoCD server, application controller, and repo server | -| `kube-system` | Traefik ingress controller, K3s system components | - -## Data Stores - -| Database | Data Stored | -| --- | --- | -| **PostgreSQL** | Users, sources, scans, service accounts, connector state, configuration | -| **ClickHouse** | Scan results, analytics, OpenTelemetry traces and logs | -| **Redis** | User sessions, Sidekiq job queues, application cache | diff --git a/docs/accessanalyzer/1.0/install/_category_.json b/docs/accessanalyzer/1.0/overview/install/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/install/_category_.json rename to docs/accessanalyzer/1.0/overview/install/_category_.json diff --git a/docs/accessanalyzer/1.0/install/dspmctl.md b/docs/accessanalyzer/1.0/overview/install/dspmctl.md similarity index 100% rename from docs/accessanalyzer/1.0/install/dspmctl.md rename to docs/accessanalyzer/1.0/overview/install/dspmctl.md diff --git a/docs/accessanalyzer/1.0/install/environmentvariables.md b/docs/accessanalyzer/1.0/overview/install/environmentvariables.md similarity index 100% rename from docs/accessanalyzer/1.0/install/environmentvariables.md rename to docs/accessanalyzer/1.0/overview/install/environmentvariables.md diff --git a/docs/accessanalyzer/1.0/install/network.md b/docs/accessanalyzer/1.0/overview/install/network.md similarity index 100% rename from docs/accessanalyzer/1.0/install/network.md rename to docs/accessanalyzer/1.0/overview/install/network.md diff --git a/docs/accessanalyzer/1.0/install/overview.md b/docs/accessanalyzer/1.0/overview/install/overview.md similarity index 100% rename from docs/accessanalyzer/1.0/install/overview.md rename to docs/accessanalyzer/1.0/overview/install/overview.md diff --git a/docs/accessanalyzer/1.0/install/postinstall.md b/docs/accessanalyzer/1.0/overview/install/postinstall.md similarity index 100% rename from docs/accessanalyzer/1.0/install/postinstall.md rename to docs/accessanalyzer/1.0/overview/install/postinstall.md diff --git a/docs/accessanalyzer/1.0/install/preflight.md b/docs/accessanalyzer/1.0/overview/install/preflight.md similarity index 100% rename from docs/accessanalyzer/1.0/install/preflight.md rename to docs/accessanalyzer/1.0/overview/install/preflight.md diff --git a/docs/accessanalyzer/1.0/install/quickinstall.md b/docs/accessanalyzer/1.0/overview/install/quickinstall.md similarity index 100% rename from docs/accessanalyzer/1.0/install/quickinstall.md rename to docs/accessanalyzer/1.0/overview/install/quickinstall.md diff --git a/docs/accessanalyzer/1.0/install/requirements.md b/docs/accessanalyzer/1.0/overview/install/requirements.md similarity index 100% rename from docs/accessanalyzer/1.0/install/requirements.md rename to docs/accessanalyzer/1.0/overview/install/requirements.md diff --git a/docs/accessanalyzer/1.0/install/security.md b/docs/accessanalyzer/1.0/overview/install/security.md similarity index 100% rename from docs/accessanalyzer/1.0/install/security.md rename to docs/accessanalyzer/1.0/overview/install/security.md diff --git a/docs/accessanalyzer/1.0/install/ssl.md b/docs/accessanalyzer/1.0/overview/install/ssl.md similarity index 100% rename from docs/accessanalyzer/1.0/install/ssl.md rename to docs/accessanalyzer/1.0/overview/install/ssl.md diff --git a/docs/accessanalyzer/1.0/install/stepbystep.md b/docs/accessanalyzer/1.0/overview/install/stepbystep.md similarity index 100% rename from docs/accessanalyzer/1.0/install/stepbystep.md rename to docs/accessanalyzer/1.0/overview/install/stepbystep.md diff --git a/docs/accessanalyzer/1.0/install/uninstall.md b/docs/accessanalyzer/1.0/overview/install/uninstall.md similarity index 100% rename from docs/accessanalyzer/1.0/install/uninstall.md rename to docs/accessanalyzer/1.0/overview/install/uninstall.md diff --git a/docs/accessanalyzer/1.0/install/upgrade.md b/docs/accessanalyzer/1.0/overview/install/upgrade.md similarity index 100% rename from docs/accessanalyzer/1.0/install/upgrade.md rename to docs/accessanalyzer/1.0/overview/install/upgrade.md diff --git a/docs/accessanalyzer/1.0/overview/keyconcepts.md b/docs/accessanalyzer/1.0/overview/keyconcepts.md index 409c8cd341..804ce89f01 100644 --- a/docs/accessanalyzer/1.0/overview/keyconcepts.md +++ b/docs/accessanalyzer/1.0/overview/keyconcepts.md @@ -1,7 +1,7 @@ --- title: "Key Concepts" description: "Sources, scans, patterns, identities, and entitlements" -sidebar_position: 30 +sidebar_position: 20 --- # Key Concepts @@ -56,7 +56,7 @@ A **scan** defines what to analyze and how. Access Analyzer supports several sca - **Identity sync scans** — Synchronize users, groups, and roles from IAM sources (Active Directory Inventory, Entra ID Users/Groups/Roles) - **Local Users and Groups scans** — Collect local account data from file servers (auto-created when an access scan is enabled) -Scans are configured during the [Connect Source wizard](/docs/accessanalyzer/1_0/gettingstarted/firstscan/configuringscan) and can be run on demand or scheduled with a cron expression. Each scan run produces a **scan execution** record with status, duration, and results. +Scans can be run on demand or scheduled with a cron expression. Each scan run produces a **scan execution** record with status, duration, and results. ## Identities and Entitlements diff --git a/docs/accessanalyzer/1.0/overview/overview.md b/docs/accessanalyzer/1.0/overview/overview.md index c74a5290d8..6dc74163a7 100644 --- a/docs/accessanalyzer/1.0/overview/overview.md +++ b/docs/accessanalyzer/1.0/overview/overview.md @@ -1,16 +1,16 @@ --- -title: "What is Access Analyzer" +title: "Intro to the Product" description: "Introduction to Netwrix Access Analyzer and its capabilities" sidebar_position: 10 --- -# What is Access Analyzer +# Intro to the Product -Netwrix Access Analyzer is a Data Security Posture Management (DSPM) platform that discovers, classifies, and secures sensitive data across your organization's file systems and cloud services. It provides visibility into who has access to what data, identifies overly permissive access, and detects sensitive data exposure. +Netwrix Access Analyzer is an on-premises Data Security Posture Management (DSPM) platform that discovers, classifies, and secures sensitive data across your organization's file systems. Deployed on your own infrastructure, it provides visibility into who has access to what data, identifies overly permissive access, and detects sensitive data exposure — all without sending data to the cloud. ## Core Capabilities -- **Data Source Discovery** — Connect to file shares (CIFS/SMB), SharePoint Online sites, and other data repositories to inventory content and access permissions +- **Data Source Discovery** — Connect to file shares (CIFS/SMB) and other on-premises data repositories to inventory content and access permissions - **Identity and Access Analysis** — Synchronize with Active Directory, Entra ID, and local groups to map identities, group memberships, and effective permissions - **Sensitive Data Detection** — Scan files for PII, credentials, PHI, and financial records using built-in patterns and custom regex rules, with compliance mappings to GDPR, CCPA, HIPAA, PCI DSS, GLBA, and CMMC - **Dashboards and Reporting** — View findings through embedded Metabase dashboards for data security posture, Active Directory insights, and sensitive data exposure @@ -18,19 +18,19 @@ Netwrix Access Analyzer is a Data Security Posture Management (DSPM) platform th ## How It Works -1. **Configure data sources** — Add file shares, cloud services, and identity providers as data sources, each with an associated service account for authentication +1. **Configure data sources** — Add file shares and identity providers as data sources, each with an associated service account for authentication 2. **Run scans** — Create access scans to enumerate permissions and sensitive data scans to classify content 3. **Review findings** — Analyze results through dashboards, reports, and the scan execution history 4. **Take action** — Identify and remediate overly permissive access, exposed sensitive data, and policy violations ## Deployment Model -Access Analyzer is deployed as a self-contained Kubernetes cluster on a single Linux VM. A one-command installer provisions all required infrastructure — including K3s, ArgoCD, databases, and application services. Updates are managed automatically through ArgoCD GitOps. +Access Analyzer is deployed on-premises as a self-contained Kubernetes cluster on a single Linux VM within your own network. A one-command installer provisions all required infrastructure — including K3s, ArgoCD, databases, and application services. No cloud connectivity is required. Updates are managed through ArgoCD GitOps. -For installation instructions, see [Installation](/docs/accessanalyzer/1_0/install/overview). +For installation instructions, see [Installation](/docs/accessanalyzer/1_0/overview/install/overview). ## What's Next -- [Architecture Overview](/docs/accessanalyzer/1_0/overview/architecture) — Understand the platform components and how they interact - [Key Concepts](/docs/accessanalyzer/1_0/overview/keyconcepts) — Learn the terminology used throughout Access Analyzer -- [Getting Started](/docs/accessanalyzer/1_0/gettingstarted/overview) — Begin configuring your first data source and scan +- [Requirements](/docs/accessanalyzer/1_0/overview/requirements/overview) — Review system and connector requirements +- [Installation](/docs/accessanalyzer/1_0/overview/install/overview) — Install Access Analyzer on your infrastructure diff --git a/docs/accessanalyzer/1.0/requirements/_category_.json b/docs/accessanalyzer/1.0/overview/requirements/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/requirements/_category_.json rename to docs/accessanalyzer/1.0/overview/requirements/_category_.json diff --git a/docs/accessanalyzer/1.0/requirements/connectors/_category_.json b/docs/accessanalyzer/1.0/overview/requirements/connectors/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/requirements/connectors/_category_.json rename to docs/accessanalyzer/1.0/overview/requirements/connectors/_category_.json diff --git a/docs/accessanalyzer/1.0/requirements/connectors/activedirectory.md b/docs/accessanalyzer/1.0/overview/requirements/connectors/activedirectory.md similarity index 100% rename from docs/accessanalyzer/1.0/requirements/connectors/activedirectory.md rename to docs/accessanalyzer/1.0/overview/requirements/connectors/activedirectory.md diff --git a/docs/accessanalyzer/1.0/requirements/connectors/cifs.md b/docs/accessanalyzer/1.0/overview/requirements/connectors/cifs.md similarity index 100% rename from docs/accessanalyzer/1.0/requirements/connectors/cifs.md rename to docs/accessanalyzer/1.0/overview/requirements/connectors/cifs.md diff --git a/docs/accessanalyzer/1.0/requirements/connectors/entraid.md b/docs/accessanalyzer/1.0/overview/requirements/connectors/entraid.md similarity index 100% rename from docs/accessanalyzer/1.0/requirements/connectors/entraid.md rename to docs/accessanalyzer/1.0/overview/requirements/connectors/entraid.md diff --git a/docs/accessanalyzer/1.0/requirements/connectors/localgroups.md b/docs/accessanalyzer/1.0/overview/requirements/connectors/localgroups.md similarity index 100% rename from docs/accessanalyzer/1.0/requirements/connectors/localgroups.md rename to docs/accessanalyzer/1.0/overview/requirements/connectors/localgroups.md diff --git a/docs/accessanalyzer/1.0/requirements/connectors/sharepointonline.md b/docs/accessanalyzer/1.0/overview/requirements/connectors/sharepointonline.md similarity index 100% rename from docs/accessanalyzer/1.0/requirements/connectors/sharepointonline.md rename to docs/accessanalyzer/1.0/overview/requirements/connectors/sharepointonline.md diff --git a/docs/accessanalyzer/1.0/requirements/database/_category_.json b/docs/accessanalyzer/1.0/overview/requirements/database/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/requirements/database/_category_.json rename to docs/accessanalyzer/1.0/overview/requirements/database/_category_.json diff --git a/docs/accessanalyzer/1.0/requirements/database/clickhouse.md b/docs/accessanalyzer/1.0/overview/requirements/database/clickhouse.md similarity index 100% rename from docs/accessanalyzer/1.0/requirements/database/clickhouse.md rename to docs/accessanalyzer/1.0/overview/requirements/database/clickhouse.md diff --git a/docs/accessanalyzer/1.0/requirements/database/postgresql.md b/docs/accessanalyzer/1.0/overview/requirements/database/postgresql.md similarity index 100% rename from docs/accessanalyzer/1.0/requirements/database/postgresql.md rename to docs/accessanalyzer/1.0/overview/requirements/database/postgresql.md diff --git a/docs/accessanalyzer/1.0/requirements/database/redis.md b/docs/accessanalyzer/1.0/overview/requirements/database/redis.md similarity index 100% rename from docs/accessanalyzer/1.0/requirements/database/redis.md rename to docs/accessanalyzer/1.0/overview/requirements/database/redis.md diff --git a/docs/accessanalyzer/1.0/requirements/overview.md b/docs/accessanalyzer/1.0/overview/requirements/overview.md similarity index 100% rename from docs/accessanalyzer/1.0/requirements/overview.md rename to docs/accessanalyzer/1.0/overview/requirements/overview.md diff --git a/docs/accessanalyzer/1.0/requirements/system/_category_.json b/docs/accessanalyzer/1.0/overview/requirements/system/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/requirements/system/_category_.json rename to docs/accessanalyzer/1.0/overview/requirements/system/_category_.json diff --git a/docs/accessanalyzer/1.0/requirements/system/hardware.md b/docs/accessanalyzer/1.0/overview/requirements/system/hardware.md similarity index 100% rename from docs/accessanalyzer/1.0/requirements/system/hardware.md rename to docs/accessanalyzer/1.0/overview/requirements/system/hardware.md diff --git a/docs/accessanalyzer/1.0/requirements/system/kubernetes.md b/docs/accessanalyzer/1.0/overview/requirements/system/kubernetes.md similarity index 100% rename from docs/accessanalyzer/1.0/requirements/system/kubernetes.md rename to docs/accessanalyzer/1.0/overview/requirements/system/kubernetes.md diff --git a/docs/accessanalyzer/1.0/requirements/system/network.md b/docs/accessanalyzer/1.0/overview/requirements/system/network.md similarity index 100% rename from docs/accessanalyzer/1.0/requirements/system/network.md rename to docs/accessanalyzer/1.0/overview/requirements/system/network.md diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/_category_.json b/docs/accessanalyzer/1.0/sensitivedatadiscovery/_category_.json deleted file mode 100644 index 6bf6249468..0000000000 --- a/docs/accessanalyzer/1.0/sensitivedatadiscovery/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Sensitive Data Discovery", - "position": 70, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/overview.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/overview.md deleted file mode 100644 index f534a637e7..0000000000 --- a/docs/accessanalyzer/1.0/sensitivedatadiscovery/overview.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: "Sensitive Data Discovery" -description: "Discover and classify sensitive data across your environment" -sidebar_position: 1 ---- - -# Sensitive Data Discovery - -Sensitive Data Discovery (SDD) in Netwrix Access Analyzer identifies and classifies sensitive information across your connected data sources. The platform uses two complementary detection methods: the Netwrix Data Classification SDK and custom regex pattern matching. - -## Workflow - -Follow these steps to discover sensitive data in your environment: - -1. **Configure detection patterns** — Select from [built-in patterns](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/builtinpatterns) or [create custom regex patterns](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/custompatterns) to define what constitutes sensitive data. -2. **Organize patterns into groups** — Use [pattern groups](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/patterngroups) to logically categorize your detection patterns. -3. **Map to compliance frameworks** — Configure [taxonomy groups](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/taxonomygroups) and [classification rules](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/classificationrules) to align findings with regulatory requirements. -4. **Run a scan** — [Execute a sensitive data scan](/docs/accessanalyzer/1_0/sensitivedatadiscovery/runningscan) against your target data sources. -5. **Review results** — Analyze [match counts](/docs/accessanalyzer/1_0/sensitivedatadiscovery/reviewingresults/matchcounts) and [classification breakdowns](/docs/accessanalyzer/1_0/sensitivedatadiscovery/reviewingresults/classificationbreakdown) to understand your data risk posture. - -## Supported Data Types - -| Category | Examples | -| --- | --- | -| PII | Social Security numbers, names, addresses, email addresses | -| Credentials | Passwords, API keys, authentication tokens | -| PHI | Medical records, health data, insurance identifiers | -| Financial Records | Credit card numbers, bank account details | - -:::note -Sensitive data scans are configured during the scan creation wizard. Ensure your detection patterns and taxonomy mappings are in place before running your first scan. -::: diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/_category_.json b/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/_category_.json deleted file mode 100644 index 868656ec39..0000000000 --- a/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Configuring Patterns", - "position": 20, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "builtinpatterns" - } -} diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/builtinpatterns.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/builtinpatterns.md deleted file mode 100644 index 0653231675..0000000000 --- a/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/builtinpatterns.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: "Built-in Patterns" -description: "Pre-configured patterns for PII, PCI, SSN, and more" -sidebar_position: 10 ---- - -# Built-in Patterns - -Netwrix Access Analyzer ships with a library of pre-configured detection patterns that identify common categories of sensitive data. These built-in patterns use the Netwrix Data Classification SDK and are ready to use without additional configuration. - -## Pattern Categories - -| Category | Description | Examples | -| --- | --- | --- | -| PII | Personally identifiable information | Social Security numbers, full names, mailing addresses, email addresses, phone numbers | -| Credentials | Authentication and access secrets | Passwords, API keys, tokens, private keys, connection strings | -| PHI | Protected health information | Medical record numbers, health plan IDs, diagnosis codes, lab results | -| Financial Records | Payment and banking data | Credit card numbers (PAN), bank account and routing numbers, tax IDs | - -## How Built-in Patterns Work - -Built-in patterns leverage two detection methods: - -- **Netwrix Data Classification SDK** — A C#/.NET-based engine that applies advanced heuristics and contextual analysis beyond simple pattern matching. -- **Regex pattern matching** — Standard regular expressions tuned for high-accuracy detection of structured data formats such as SSNs, credit card numbers, and IBANs. - -:::note -Built-in patterns cannot be edited directly. To modify detection behavior, create a [custom pattern](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/custompatterns) and organize it into a [pattern group](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/patterngroups). -::: - -## Next Steps - -- [Create custom regex patterns](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/custompatterns) for organization-specific data formats -- [Organize patterns into groups](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/patterngroups) for streamlined scan configuration diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/custompatterns.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/custompatterns.md deleted file mode 100644 index 8645e34568..0000000000 --- a/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/custompatterns.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: "Creating Custom Regex Patterns" -description: "Define custom regex patterns for sensitive data detection" -sidebar_position: 20 ---- - -# Creating Custom Regex Patterns - -Custom regex patterns allow you to extend sensitive data detection beyond the built-in library. Define patterns that match organization-specific data formats such as internal account numbers, proprietary identifiers, or region-specific document formats. - -## Creating a Custom Pattern - -To create a custom regex pattern: - -1. Navigate to the **Sensitive Data Discovery** section in Access Analyzer. -2. Select **Patterns** and click **Add Pattern**. -3. Provide a **Name** and optional **Description** for the pattern. -4. Enter the **Regex Expression** that defines the match criteria. -5. Select the appropriate **Category** (PII, Credentials, PHI, or Financial Records). -6. Click **Save** to register the pattern. - -:::note -Custom patterns can also be added programmatically via the Access Analyzer API. Refer to the API documentation for endpoint details and payload format. -::: - -## Regex Best Practices - -- **Be specific** — Overly broad patterns increase false positives. Use anchors, character classes, and quantifiers to narrow matches. -- **Test before deploying** — Validate your regex against sample data to confirm it captures the intended formats without excessive noise. -- **Use named groups** — Where supported, named capture groups improve readability and facilitate downstream processing. - -## Example - -A pattern to detect a custom internal employee ID formatted as `EMP-` followed by six digits: - -``` -EMP-\d{6} -``` - -:::warning -Poorly constructed regex patterns may degrade scan performance. Avoid unbounded quantifiers and excessive backtracking in pattern definitions. -::: - -## Next Steps - -- [Organize patterns into groups](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/patterngroups) for easier management -- [Map patterns to compliance frameworks](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/taxonomygroups) using taxonomy groups diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/patterngroups.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/patterngroups.md deleted file mode 100644 index 9643c03154..0000000000 --- a/docs/accessanalyzer/1.0/sensitivedatadiscovery/patterns/patterngroups.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: "Pattern Groups" -description: "Organizing patterns into logical groups" -sidebar_position: 30 ---- - -# Pattern Groups - -Pattern groups organize individual detection patterns into logical collections. Grouping patterns by category or purpose simplifies scan configuration and makes it easier to apply consistent detection policies across multiple scans. - -## How Pattern Groups Work - -A pattern group is a named container that holds one or more detection patterns (built-in or custom). When you configure a sensitive data scan, you select pattern groups rather than individual patterns, which reduces configuration complexity. - -Common grouping strategies include: - -- **By data type** — Group all PII patterns together, all credential patterns together, and so on. -- **By compliance framework** — Group patterns that satisfy a specific regulation such as HIPAA or PCI DSS. -- **By business unit** — Group patterns relevant to a particular department or data domain. - -## Managing Pattern Groups - -To create or edit a pattern group: - -1. Navigate to **Sensitive Data Discovery** > **Patterns**. -2. Select the **Pattern Groups** tab. -3. Click **Add Group** to create a new group, or select an existing group to edit it. -4. Provide a **Name** and optional **Description**. -5. Add or remove patterns from the group using the pattern selector. -6. Click **Save**. - -:::note -A single pattern can belong to multiple groups. Changes to a pattern are reflected in all groups that reference it. -::: - -## Next Steps - -- [Configure taxonomy groups](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/taxonomygroups) to map pattern groups to compliance frameworks -- [Run a sensitive data scan](/docs/accessanalyzer/1_0/sensitivedatadiscovery/runningscan) using your configured pattern groups diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/_category_.json b/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/_category_.json deleted file mode 100644 index 8d68d0c5ea..0000000000 --- a/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Reviewing Results", - "position": 50, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "matchcounts" - } -} diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/classificationbreakdown.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/classificationbreakdown.md deleted file mode 100644 index 74a5711b20..0000000000 --- a/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/classificationbreakdown.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: "Classification Breakdown" -description: "Analyzing results by classification category" -sidebar_position: 20 ---- - -# Classification Breakdown - -The classification breakdown view organizes sensitive data scan results by taxonomy group and compliance framework. This view helps you assess regulatory exposure and prioritize remediation efforts based on the frameworks most relevant to your organization. - -## Viewing the Breakdown - -To access the classification breakdown: - -1. Navigate to the **Scans** section and select a completed scan. -2. Open the **Results** tab. -3. Select the **Classification Breakdown** view. - -The breakdown displays a summary of matches grouped by each applicable compliance framework. - -## Framework Summary - -| Column | Description | -| --- | --- | -| **Framework** | The compliance standard (GDPR, CCPA, HIPAA, PCI DSS, GLBA, CMMC) | -| **Total Matches** | Aggregate count of sensitive data matches mapped to this framework | -| **Files Affected** | Number of distinct files containing matches for this framework | -| **Top Patterns** | The most frequently triggered detection patterns within the framework | - -## Interpreting Results - -- A file may appear under multiple frameworks if its contents match classification rules mapped to different taxonomy groups. -- The **Top Patterns** column highlights which data types contribute the most matches, helping you identify the most common exposure areas. -- Use the breakdown to generate framework-specific remediation plans by focusing on the frameworks with the highest match counts. - -:::note -Classification breakdown results depend on the [taxonomy groups](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/taxonomygroups) and [classification rules](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/classificationrules) configured at the time of the scan. Update your taxonomy mappings and re-scan to reflect new compliance requirements. -::: - -## Next Steps - -- [Export findings](/docs/accessanalyzer/1_0/dashboards/metabase/exportingdata) for compliance reporting -- [View dashboards](/docs/accessanalyzer/1_0/dashboards/overview) for a high-level risk summary diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/matchcounts.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/matchcounts.md deleted file mode 100644 index 2dd3d19f26..0000000000 --- a/docs/accessanalyzer/1.0/sensitivedatadiscovery/reviewingresults/matchcounts.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: "Match Counts and Locations" -description: "Viewing match counts per file and location details" -sidebar_position: 10 ---- - -# Match Counts and Locations - -After a sensitive data scan completes, the results view displays match counts that summarize how many sensitive data instances were detected, organized by file, pattern, and compliance framework. - -## Understanding Match Counts - -Match counts are reported at three levels: - -| Level | Description | -| --- | --- | -| **Per File** | Total number of sensitive data matches found in each scanned file | -| **Per Pattern** | Number of matches attributed to each detection pattern (for example, SSN, credit card number) | -| **Per Framework** | Aggregate match count grouped by compliance framework (GDPR, HIPAA, PCI DSS, and others) | - -## Viewing Match Details - -To review match counts for a completed scan: - -1. Navigate to the **Scans** section and select the completed scan. -2. Open the **Results** tab to view the summary. -3. Use the **Files** view to see match counts per file, sorted by the number of matches in descending order. -4. Click on a specific file to view the individual pattern matches detected within it. -5. Use the **Patterns** view to see total matches per detection pattern across all scanned files. - -:::note -Match counts reflect the number of pattern matches, not the number of unique sensitive data values. A single file containing the same SSN in multiple locations is counted as multiple matches. -::: - -## Filtering Results - -Use the filter controls to narrow results by: - -- **Data type** — PII, Credentials, PHI, or Financial Records -- **Pattern group** — Filter by a specific pattern group applied during the scan -- **Severity** — Focus on high-priority findings - -## Next Steps - -- [View classification breakdowns](/docs/accessanalyzer/1_0/sensitivedatadiscovery/reviewingresults/classificationbreakdown) to analyze results by compliance framework -- [Access dashboards](/docs/accessanalyzer/1_0/dashboards/overview) for a visual summary of findings diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/runningscan.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/runningscan.md deleted file mode 100644 index 78306fe3bc..0000000000 --- a/docs/accessanalyzer/1.0/sensitivedatadiscovery/runningscan.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: "Running a Sensitive Data Scan" -description: "Executing a sensitive data scan and monitoring progress" -sidebar_position: 40 ---- - -# Running a Sensitive Data Scan - -Sensitive data scans analyze files across your connected data sources to detect content matching your configured detection patterns. Scans are configured and launched through the scan creation wizard. - -## Prerequisites - -Before running a sensitive data scan, ensure the following are in place: - -- At least one data source is connected and accessible -- Detection [patterns](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/builtinpatterns) or [pattern groups](/docs/accessanalyzer/1_0/sensitivedatadiscovery/patterns/patterngroups) are configured -- [Taxonomy groups](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/taxonomygroups) and [classification rules](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/classificationrules) are defined for compliance mapping - -## Launching a Scan - -1. Navigate to the **Scans** section in Access Analyzer. -2. Click **Create Scan** to open the scan creation wizard. -3. Select the target **Data Source(s)** to scan. -4. Under **Scan Options**, enable **Sensitive Data Discovery**. -5. Choose the **Pattern Groups** to apply during the scan. -6. Review the scan configuration summary and click **Start Scan**. - -## Monitoring Progress - -Once a scan is running, you can monitor its status from the **Scans** page. The scan detail view displays: - -- **Progress** — Percentage of files processed -- **Files Scanned** — Count of files analyzed so far -- **Matches Found** — Running total of sensitive data matches - -:::warning -Sensitive data scans are resource-intensive. The `sensitive-data-scan` and `data-classification` serverless functions handle detection workloads. Schedule large scans during off-peak hours to minimize impact on system performance. -::: - -## Next Steps - -- [Review match counts](/docs/accessanalyzer/1_0/sensitivedatadiscovery/reviewingresults/matchcounts) after the scan completes -- [Analyze classification breakdowns](/docs/accessanalyzer/1_0/sensitivedatadiscovery/reviewingresults/classificationbreakdown) by compliance framework diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/_category_.json b/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/_category_.json deleted file mode 100644 index ce0fe0e2ed..0000000000 --- a/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Taxonomy and Classification", - "position": 30, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "taxonomygroups" - } -} diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/autovscustom.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/autovscustom.md deleted file mode 100644 index 0f6c9de35d..0000000000 --- a/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/autovscustom.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: "Auto vs Custom Classification" -description: "Automatic and custom classification methods" -sidebar_position: 30 ---- - -# Auto vs Custom Classification - -Netwrix Access Analyzer supports two classification approaches for sensitive data: automatic (built-in) classification and custom classification. You can use either method independently or combine them for comprehensive coverage. - -## Automatic Classification - -Automatic classification uses the built-in patterns and taxonomy groups that ship with Access Analyzer. This approach requires no upfront configuration and covers common sensitive data categories out of the box. - -**Advantages:** - -- Ready to use immediately after installation -- Covers standard compliance frameworks (GDPR, CCPA, HIPAA, PCI DSS, GLBA, CMMC) -- Maintained and updated by Netwrix through the Data Classification SDK - -**Best for:** Organizations that need quick time-to-value and standard regulatory coverage. - -## Custom Classification - -Custom classification uses organization-defined regex patterns, pattern groups, and taxonomy mappings. This approach provides full control over what data is detected and how it is categorized. - -**Advantages:** - -- Detects proprietary or non-standard data formats -- Maps findings to internal policies beyond standard frameworks -- Supports region-specific or industry-specific identifiers - -**Best for:** Organizations with unique data formats or compliance requirements not covered by built-in rules. - -## Combining Both Approaches - -For most deployments, a hybrid approach provides the best coverage. Use automatic classification as a baseline, then layer custom patterns for organization-specific needs. - -:::note -Custom rules take precedence over automatic rules when both match the same data and the custom rule has a higher priority. See [Classification Rules](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/classificationrules) for details on priority settings. -::: diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/classificationrules.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/classificationrules.md deleted file mode 100644 index 028e7e4ed0..0000000000 --- a/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/classificationrules.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: "Classification Rules" -description: "Defining rules that combine patterns and taxonomy" -sidebar_position: 20 ---- - -# Classification Rules - -Classification rules connect detection patterns to taxonomy groups, determining how identified sensitive data is categorized and which compliance frameworks apply to each finding. A rule specifies the conditions under which a pattern match is classified under a particular taxonomy. - -## Rule Components - -Each classification rule consists of: - -| Component | Description | -| --- | --- | -| **Name** | A descriptive label for the rule | -| **Pattern or Pattern Group** | The detection patterns that trigger the rule | -| **Taxonomy Group** | The compliance framework or category the match maps to | -| **Priority** | Determines precedence when multiple rules match the same data | - -## Creating a Classification Rule - -1. Navigate to **Sensitive Data Discovery** > **Taxonomy**. -2. Select the **Classification Rules** tab. -3. Click **Add Rule**. -4. Enter a **Name** for the rule. -5. Select the **Pattern** or **Pattern Group** that triggers this classification. -6. Choose the **Taxonomy Group** the rule maps to (for example, HIPAA, PCI DSS, or a custom group). -7. Set the **Priority** level to control rule precedence. -8. Click **Save**. - -:::note -When a single file matches multiple classification rules, all applicable taxonomy groups are reported. Priority determines which classification is displayed first in summary views. -::: - -## Next Steps - -- [Review built-in versus custom classification](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/autovscustom) to decide which approach fits your needs -- [Run a scan](/docs/accessanalyzer/1_0/sensitivedatadiscovery/runningscan) to apply your classification rules against live data diff --git a/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/taxonomygroups.md b/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/taxonomygroups.md deleted file mode 100644 index 54e9e01635..0000000000 --- a/docs/accessanalyzer/1.0/sensitivedatadiscovery/taxonomy/taxonomygroups.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: "Taxonomy Groups" -description: "Creating and managing data classification categories" -sidebar_position: 10 ---- - -# Taxonomy Groups - -Taxonomy groups map classification rules to compliance frameworks, enabling you to align sensitive data findings with regulatory and organizational requirements. Each taxonomy group represents a compliance standard or internal policy against which scan results are evaluated. - -## Supported Compliance Frameworks - -Access Analyzer includes built-in taxonomy groups for the following frameworks: - -| Framework | Description | -| --- | --- | -| GDPR | General Data Protection Regulation — EU personal data protection | -| CCPA | California Consumer Privacy Act — California resident data rights | -| HIPAA | Health Insurance Portability and Accountability Act — protected health information | -| PCI DSS | Payment Card Industry Data Security Standard — cardholder data protection | -| GLBA | Gramm-Leach-Bliley Act — financial institution consumer data | -| CMMC | Cybersecurity Maturity Model Certification — defense contractor requirements | - -## Managing Taxonomy Groups - -To create or modify a taxonomy group: - -1. Navigate to **Sensitive Data Discovery** > **Taxonomy**. -2. Select the **Taxonomy Groups** tab. -3. Click **Add Group** to create a new group, or select an existing group to edit. -4. Provide a **Name** and select the target **Compliance Framework**. -5. Associate [classification rules](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/classificationrules) that define which data types fall under this group. -6. Click **Save**. - -:::note -Built-in taxonomy groups are pre-mapped to their respective frameworks. You can create additional groups for internal policies or regional regulations not covered by the defaults. -::: - -## Next Steps - -- [Define classification rules](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/classificationrules) to control how data is categorized within each taxonomy group -- [Compare built-in and custom classification](/docs/accessanalyzer/1_0/sensitivedatadiscovery/taxonomy/autovscustom) approaches diff --git a/docs/accessanalyzer/1.0/troubleshooting/_category_.json b/docs/accessanalyzer/1.0/troubleshooting/_category_.json deleted file mode 100644 index 53df54fda4..0000000000 --- a/docs/accessanalyzer/1.0/troubleshooting/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Monitoring and Troubleshooting", - "position": 100, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/troubleshooting/commonissues/_category_.json b/docs/accessanalyzer/1.0/troubleshooting/commonissues/_category_.json deleted file mode 100644 index feba67eef4..0000000000 --- a/docs/accessanalyzer/1.0/troubleshooting/commonissues/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Common Issues", - "position": 40, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "connectionfailures" - } -} diff --git a/docs/accessanalyzer/1.0/troubleshooting/commonissues/connectionfailures.md b/docs/accessanalyzer/1.0/troubleshooting/commonissues/connectionfailures.md deleted file mode 100644 index f13e0f0872..0000000000 --- a/docs/accessanalyzer/1.0/troubleshooting/commonissues/connectionfailures.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: "Connection Failures" -description: "Diagnosing and resolving connector connection issues" -sidebar_position: 10 ---- - -# Connection Failures - -Access Analyzer connects to external data sources using protocols such as SMB, LDAP, and Microsoft Graph API. Connection failures prevent scans from running and must be resolved before data collection can proceed. - -## Diagnostic Steps - -1. **Check the connector-api pod status:** - -```bash -kubectl get pods -n access-analyzer -l app=connector-api -kubectl logs -n access-analyzer deploy/connector-api --tail=100 -``` - -2. **Verify network connectivity** from the connector pod to the target: - -```bash -kubectl exec -n access-analyzer deploy/connector-api -- curl -v https://: -``` - -3. **Review the source configuration** in the Access Analyzer web UI. Confirm that the hostname, port, and credentials are correct. - -## SMB Connection Failures - -- Verify that TCP port **445** is open between the Access Analyzer cluster and the target file server. -- Confirm that the service account has the required share and NTFS permissions. -- Check for DNS resolution issues by running `nslookup ` from within the connector pod. - -## LDAP Connection Failures - -- Verify that TCP port **389** (LDAP) or **636** (LDAPS) is reachable. -- Confirm that the bind DN and password are correct. -- For LDAPS, ensure the target server's TLS certificate is trusted. Self-signed certificates may require adding a CA bundle. - -## Microsoft Graph API Failures - -- Confirm that the Azure AD application registration has the required API permissions. -- Verify that the client ID, client secret, and tenant ID are correct and that the secret has not expired. -- Check outbound HTTPS connectivity to `https://graph.microsoft.com` and `https://login.microsoftonline.com`. - -```bash -kubectl exec -n access-analyzer deploy/connector-api -- curl -s -o /dev/null -w "%{http_code}" https://graph.microsoft.com/v1.0/ -``` - -## General Troubleshooting - -| Symptom | Likely Cause | Action | -| --- | --- | --- | -| Connection timeout | Firewall or network policy blocking traffic | Verify firewall rules and Kubernetes network policies | -| Authentication error | Invalid or expired credentials | Update credentials in the source configuration | -| TLS handshake failure | Certificate mismatch or expired certificate | Verify TLS certificates on the target service | -| DNS resolution failure | Incorrect hostname or missing DNS entry | Test DNS from within the connector pod | - -:::note -Connection tests run from the `connector-api` pod. Network access from your local machine does not guarantee access from within the cluster. -::: diff --git a/docs/accessanalyzer/1.0/troubleshooting/commonissues/databaseconnectivity.md b/docs/accessanalyzer/1.0/troubleshooting/commonissues/databaseconnectivity.md deleted file mode 100644 index fb2aebe74c..0000000000 --- a/docs/accessanalyzer/1.0/troubleshooting/commonissues/databaseconnectivity.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: "Database Connectivity" -description: "Resolving PostgreSQL, ClickHouse, and Redis connectivity issues" -sidebar_position: 30 ---- - -# Database Connectivity - -Access Analyzer relies on three backing data stores: PostgreSQL for relational data, ClickHouse for analytics and trace storage, and Redis for sessions, caching, and job queues. Connectivity failures to any of these services impact application functionality. - -## Checking Pod Status - -**Verify that all database pods are running:** - -```bash -kubectl get pods -n access-analyzer -l app=postgresql -kubectl get pods -n access-analyzer -l app=clickhouse -kubectl get pods -n access-analyzer -l app=redis -``` - -A pod not in `Running` status requires immediate attention. Use `kubectl describe pod -n access-analyzer` to inspect events and error details. - -## PostgreSQL - -PostgreSQL stores core application data including user accounts, source configurations, and scan results. - -**Test connectivity from the core-api pod:** - -```bash -kubectl exec -n access-analyzer deploy/core-api -- pg_isready -h postgresql -p 5432 -``` - -**Check active connections:** - -```bash -kubectl exec -n access-analyzer deploy/postgresql -- psql -U postgres -c "SELECT count(*) FROM pg_stat_activity;" -``` - -Common issues: -- **Too many connections** -- The connection pool is exhausted. Restart the application pods or increase the pool size. -- **Pod in CrashLoopBackOff** -- Check PostgreSQL logs for disk space or corruption errors. - -## ClickHouse - -ClickHouse stores analytics data and OpenTelemetry traces in the `access_analyzer_logs` database. - -**Test connectivity:** - -```bash -kubectl exec -n access-analyzer deploy/clickhouse -- clickhouse-client --query "SELECT 1" -``` - -**Check database availability:** - -```bash -kubectl exec -n access-analyzer deploy/clickhouse -- clickhouse-client --query "SHOW DATABASES" -``` - -Common issues: -- **Disk pressure** -- ClickHouse can consume significant storage for trace and analytics data. Monitor disk usage with `kubectl exec -n access-analyzer deploy/clickhouse -- df -h`. -- **Query timeout** -- Large analytical queries can time out. Check ClickHouse server logs for slow query warnings. - -## Redis - -Redis provides session storage, caching, and serves as the job queue backend for Sidekiq. - -**Test connectivity:** - -```bash -kubectl exec -n access-analyzer deploy/redis -- redis-cli ping -``` - -A successful response returns `PONG`. - -**Check memory usage:** - -```bash -kubectl exec -n access-analyzer deploy/redis -- redis-cli info memory | grep used_memory_human -``` - -Common issues: -- **MaxMemory reached** -- Redis evicts keys or rejects writes when memory is full. Increase the memory limit or review eviction policies. -- **Connection refused** -- The Redis pod may have restarted. Check pod status and events. - -## Deep Health Check - -Use the application health endpoint to validate connectivity to all backing services at once: - -```bash -kubectl exec -n access-analyzer deploy/core-api -- curl -s http://localhost:3000/api/v1/monitoring/__health -``` - -This endpoint reports the status of each backing service and identifies which connection is failing. See [Service Health Endpoints](/docs/accessanalyzer/1.0/troubleshooting/healthchecks/endpoints) for more details. - -:::warning -Database connectivity failures cascade across the application. If multiple services report errors simultaneously, start by verifying database pod health before troubleshooting individual application pods. -::: diff --git a/docs/accessanalyzer/1.0/troubleshooting/commonissues/scanerrors.md b/docs/accessanalyzer/1.0/troubleshooting/commonissues/scanerrors.md deleted file mode 100644 index 4bd3cf333c..0000000000 --- a/docs/accessanalyzer/1.0/troubleshooting/commonissues/scanerrors.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: "Scan Errors" -description: "Common scan execution errors and solutions" -sidebar_position: 20 ---- - -# Scan Errors - -Scan errors occur when Access Analyzer encounters problems during data collection from configured sources. This page covers common scan errors, their causes, and resolution steps. - -## Checking Scan Status - -Review scan status in the Access Analyzer web UI or check the logs from the relevant pods: - -```bash -kubectl logs -n access-analyzer deploy/core-api --tail=200 | grep -i scan -kubectl logs -n access-analyzer deploy/connector-api --tail=200 | grep -i scan -``` - -## Common Scan Errors - -### Scan Timeout - -Scans that exceed the configured timeout are terminated automatically. - -- **Cause**: Large data sources, slow network connectivity, or insufficient worker resources. -- **Resolution**: Increase the scan timeout if appropriate, reduce the scan scope, or allocate additional resources to worker pods. - -### Pod Failures During Scan - -If the pod executing a scan is killed or restarted mid-scan, the scan fails without completing. - -```bash -kubectl get pods -n access-analyzer --field-selector=status.phase=Failed -kubectl describe pod -n access-analyzer -``` - -- **Cause**: OOMKilled (out of memory), node eviction, or liveness probe timeout. -- **Resolution**: Check pod events for `OOMKilled` status. Increase memory limits for the affected pod if needed. Review node resource pressure with `kubectl top nodes`. - -### Permission Denied Errors - -The scan account lacks the required permissions on the target data source. - -- **Cause**: Insufficient privileges for the configured service account. -- **Resolution**: Verify that the service account has the permissions documented for the source type. See [Connection Failures](/docs/accessanalyzer/1.0/troubleshooting/commonissues/connectionfailures) for protocol-specific requirements. - -### Partial Scan Results - -A scan completes but returns fewer results than expected. - -- **Cause**: Access denied on a subset of resources, or rate limiting by the target API. -- **Resolution**: Review the scan logs for warnings about skipped resources. For API-based sources, check for throttling responses (HTTP 429). - -## Reviewing Scan Job History - -Failed scan jobs appear in the Sidekiq **Retries** or **Dead** tab. See [Failed Job Troubleshooting](/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/failedjobs) for instructions on inspecting and retrying failed jobs. - -:::warning -If scans fail consistently across multiple sources, check cluster-wide resource availability and backing service health before investigating individual source configurations. -::: diff --git a/docs/accessanalyzer/1.0/troubleshooting/healthchecks/_category_.json b/docs/accessanalyzer/1.0/troubleshooting/healthchecks/_category_.json deleted file mode 100644 index affcb1f52d..0000000000 --- a/docs/accessanalyzer/1.0/troubleshooting/healthchecks/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Health Checks", - "position": 10, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "probes" - } -} diff --git a/docs/accessanalyzer/1.0/troubleshooting/healthchecks/endpoints.md b/docs/accessanalyzer/1.0/troubleshooting/healthchecks/endpoints.md deleted file mode 100644 index 772ef5edf7..0000000000 --- a/docs/accessanalyzer/1.0/troubleshooting/healthchecks/endpoints.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: "Service Health Endpoints" -description: "Service-specific health check URLs" -sidebar_position: 20 ---- - -# Service Health Endpoints - -Access Analyzer exposes several HTTP health check endpoints that report on service availability. Use these endpoints to verify that application services are running and responsive. - -## Available Endpoints - -| Endpoint | Purpose | Expected Response | -| --- | --- | --- | -| `/health/live` | Liveness check. Confirms the process is running. | `200 OK` | -| `/health/ready` | Readiness check. Confirms the service can handle requests. | `200 OK` | -| `/api/v1/monitoring/__health` | Deep health check. Validates connectivity to backing services (database, cache). | `200 OK` with JSON status | - -## Querying Health Endpoints - -**From within the cluster, use `kubectl exec` to curl a health endpoint:** - -```bash -kubectl exec -n access-analyzer deploy/core-api -- curl -s http://localhost:3000/health/live -``` - -**Check the readiness endpoint:** - -```bash -kubectl exec -n access-analyzer deploy/core-api -- curl -s http://localhost:3000/health/ready -``` - -**Run the deep health check to verify backing service connectivity:** - -```bash -kubectl exec -n access-analyzer deploy/core-api -- curl -s http://localhost:3000/api/v1/monitoring/__health -``` - -The deep health check at `/api/v1/monitoring/__health` validates that the application can reach PostgreSQL, ClickHouse, and Redis. A failure response from this endpoint identifies which backing service is unreachable. - -## Interpreting Results - -- A `200 OK` response indicates the service is healthy. -- A non-200 response or connection timeout indicates a problem. Check the pod logs for additional context. -- If `/health/live` passes but `/health/ready` fails, the service is running but cannot process requests, typically due to a dependency being unavailable. - -:::note -The `/api/v1/monitoring/__health` endpoint performs active checks against all backing services. Use it for thorough health verification, but avoid calling it at high frequency as it places load on downstream systems. -::: diff --git a/docs/accessanalyzer/1.0/troubleshooting/healthchecks/probes.md b/docs/accessanalyzer/1.0/troubleshooting/healthchecks/probes.md deleted file mode 100644 index 8f2b0697b8..0000000000 --- a/docs/accessanalyzer/1.0/troubleshooting/healthchecks/probes.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: "Liveness and Readiness Probes" -description: "Kubernetes health probe endpoints" -sidebar_position: 10 ---- - -# Liveness and Readiness Probes - -Kubernetes uses liveness and readiness probes to monitor the health of pods in the Access Analyzer deployment. Understanding these probes helps you diagnose pod restarts and service availability issues. - -## How Probes Work - -- **Liveness probes** determine whether a container is running. If a liveness probe fails, Kubernetes restarts the container. -- **Readiness probes** determine whether a container is ready to accept traffic. If a readiness probe fails, Kubernetes removes the pod from service endpoints until it passes again. - -## Checking Probe Status - -**View the current state of all pods in the Access Analyzer namespace:** - -```bash -kubectl get pods -n access-analyzer -``` - -A pod in `CrashLoopBackOff` status typically indicates repeated liveness probe failures. A pod showing `0/1 Ready` may be failing its readiness probe. - -**Inspect probe configuration and recent events for a specific pod:** - -```bash -kubectl describe pod -n access-analyzer -``` - -Look for the `Liveness` and `Readiness` fields in the output to see the probe endpoint, interval, timeout, and failure threshold. The **Events** section at the bottom shows recent probe failures and container restarts. - -**View logs from a pod that is restarting:** - -```bash -kubectl logs -n access-analyzer --previous -``` - -The `--previous` flag retrieves logs from the last terminated container, which is useful when a pod has already restarted. - -## Key Pods to Monitor - -| Pod | Purpose | -| --- | --- | -| `core-api` | Primary API server | -| `webapp` | Web application frontend | -| `connector-api` | Source connector service | -| `postgresql` | Relational data store | -| `clickhouse` | Analytics data store | -| `redis` | Session and cache store | - -:::warning -Frequent pod restarts caused by probe failures often indicate resource pressure (memory or CPU) rather than application bugs. Check node resource utilization with `kubectl top nodes` before investigating application-level issues. -::: diff --git a/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/_category_.json b/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/_category_.json deleted file mode 100644 index 53ae508120..0000000000 --- a/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Background Job Monitoring", - "position": 30, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "sidekiq" - } -} diff --git a/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/failedjobs.md b/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/failedjobs.md deleted file mode 100644 index b6749b9aa9..0000000000 --- a/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/failedjobs.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: "Failed Job Troubleshooting" -description: "Diagnosing and resolving failed background jobs" -sidebar_position: 30 ---- - -# Failed Job Troubleshooting - -When a Sidekiq background job encounters an error, it enters the retry cycle. Jobs that exhaust all retry attempts move to the dead set. This page explains how to find, diagnose, and resolve failed jobs. - -## Finding Failed Jobs - -Open the [Sidekiq Dashboard](/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/sidekiq) and navigate to the following tabs: - -- **Retries** -- Jobs that failed and are awaiting automatic retry. Each entry displays the error class, error message, and the number of retries attempted. -- **Dead** -- Jobs that exhausted all retry attempts. Dead jobs are not retried automatically and require manual action. - -## Retry Behavior - -Sidekiq uses an exponential backoff strategy for retries. The delay between retries increases with each attempt, following the formula: - -``` -(retry_count ^ 4) + 15 + (random(10) * (retry_count + 1)) seconds -``` - -By default, a job retries up to 25 times before being moved to the dead set. This means a failing job may continue retrying for approximately 21 days before it is considered dead. - -## Diagnosing Failures - -1. **Check the error message** in the Retries or Dead tab. The error class and message typically indicate the root cause (for example, a connection timeout or validation error). -2. **Review application logs** for the time of the failure: - -```bash -kubectl logs -n access-analyzer deploy/core-api --since=1h | grep -i error -``` - -3. **Check backing service health** -- Many job failures stem from database or Redis connectivity issues. See [Database Connectivity](/docs/accessanalyzer/1.0/troubleshooting/commonissues/databaseconnectivity). - -## Handling Dead Jobs - -From the **Dead** tab in the Sidekiq dashboard, you can: - -- **Retry** a specific dead job to re-enqueue it for processing. -- **Delete** a dead job to remove it permanently. -- **Retry All** to re-enqueue all dead jobs at once. - -:::warning -Before retrying dead jobs, ensure the underlying issue has been resolved. Retrying jobs without fixing the root cause will result in repeated failures. -::: - -## Common Failure Causes - -| Cause | Symptoms | Resolution | -| --- | --- | --- | -| Redis unavailable | All jobs fail simultaneously | Verify Redis pod health | -| Database timeout | Jobs in `scans` or `syncs` queues fail | Check PostgreSQL/ClickHouse connectivity | -| External API error | Connector-related jobs fail | Verify source credentials and network access | -| Memory pressure | Jobs killed mid-execution | Increase worker pod memory limits | diff --git a/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/queues.md b/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/queues.md deleted file mode 100644 index 3dc007d084..0000000000 --- a/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/queues.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: "Job Queues and Priorities" -description: "Understanding job queue structure and priority levels" -sidebar_position: 20 ---- - -# Job Queues and Priorities - -Access Analyzer processes background work through seven Sidekiq queues, each serving a specific purpose. Understanding queue roles and priorities helps you identify processing bottlenecks and backpressure. - -## Queue Overview - -| Queue | Priority | Purpose | -| --- | --- | --- | -| `critical` | Highest | System-critical operations that must complete promptly | -| `scans` | High | Data source scan execution | -| `syncs` | High | Data synchronization between sources and the platform | -| `scheduler` | Medium | Periodic task scheduling and orchestration | -| `default` | Medium | General-purpose background work | -| `mailers` | Low | Email notification delivery | -| `low` | Lowest | Deferred or non-urgent tasks | - -Sidekiq workers process queues in priority order. Higher-priority queues are drained before lower-priority ones. - -## Monitoring Queue Depth - -**From the Sidekiq dashboard**, navigate to the **Queues** tab to view the current size of each queue. A queue size that grows continuously indicates that jobs are being enqueued faster than workers can process them. - -**From the command line, query Prometheus for queue sizes:** - -```bash -kubectl exec -n access-analyzer deploy/prometheus -- \ - promtool query instant http://localhost:9090 'sidekiq_queue_size' -``` - -## Identifying Backpressure - -Backpressure occurs when one or more queues accumulate jobs faster than they are processed. Common causes include: - -- **Resource constraints** -- Insufficient CPU or memory on worker pods. Check with `kubectl top pods -n access-analyzer`. -- **Downstream dependency failures** -- Database or external service unavailability causing job retries and requeuing. -- **Large scan jobs** -- A scan targeting a large data source can consume worker capacity, delaying other queues. - -:::warning -If the `critical` queue has a sustained non-zero depth, investigate immediately. Delayed critical jobs can affect system stability and data consistency. -::: - -## Corrective Actions - -- Scale worker replicas if resource limits allow. -- Investigate and resolve downstream dependency failures (see [Database Connectivity](/docs/accessanalyzer/1.0/troubleshooting/commonissues/databaseconnectivity)). -- Stagger large scan jobs to avoid overwhelming worker capacity. diff --git a/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/sidekiq.md b/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/sidekiq.md deleted file mode 100644 index a7b43638c9..0000000000 --- a/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/sidekiq.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: "Sidekiq Dashboard" -description: "Monitoring background jobs via the Sidekiq web UI" -sidebar_position: 10 ---- - -# Sidekiq Dashboard - -Access Analyzer uses Sidekiq to process background jobs such as scans, syncs, and scheduled tasks. The Sidekiq web dashboard provides real-time visibility into job processing, queue health, and worker status. - -## Accessing the Dashboard - -The Sidekiq dashboard is available at the `/sidekiq` path on your Access Analyzer instance: - -``` -https:///sidekiq -``` - -The dashboard requires authentication. Enter the configured username and password when prompted. - -:::note -Dashboard credentials are set during installation. Contact your system administrator if you do not have the credentials. -::: - -## Dashboard Capabilities - -The Sidekiq web UI provides the following views: - -- **Dashboard** -- Real-time graph of processed and failed jobs over time. -- **Busy** -- Lists workers currently executing jobs, including the job class and arguments. -- **Queues** -- Displays all queues with their current size. Use this to identify backpressure. -- **Retries** -- Shows jobs that failed and are scheduled for automatic retry. -- **Scheduled** -- Lists jobs enqueued for future execution. -- **Dead** -- Contains jobs that exhausted all retry attempts. These require manual intervention. - -## Checking Job Throughput - -From the dashboard home page, review the **Processed** and **Failed** counters. A healthy system shows a steadily increasing processed count with a low or zero failed count. - -If the failed count is climbing, navigate to the **Retries** tab to inspect the error messages and determine the root cause. - -## Infrastructure Dependency - -Sidekiq depends on Redis for job storage and queue management. If the Sidekiq dashboard is unreachable or shows no data, verify that the Redis pod is running: - -```bash -kubectl get pods -n access-analyzer -l app=redis -``` - -See [Job Queues and Priorities](/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/queues) for details on individual queue behavior. diff --git a/docs/accessanalyzer/1.0/troubleshooting/observability/_category_.json b/docs/accessanalyzer/1.0/troubleshooting/observability/_category_.json deleted file mode 100644 index d6e5ecaf0a..0000000000 --- a/docs/accessanalyzer/1.0/troubleshooting/observability/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Observability", - "position": 20, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "opentelemetry" - } -} diff --git a/docs/accessanalyzer/1.0/troubleshooting/observability/opentelemetry.md b/docs/accessanalyzer/1.0/troubleshooting/observability/opentelemetry.md deleted file mode 100644 index d9d1ec28e6..0000000000 --- a/docs/accessanalyzer/1.0/troubleshooting/observability/opentelemetry.md +++ /dev/null @@ -1,76 +0,0 @@ ---- -title: "OpenTelemetry Traces and Metrics" -description: "Distributed tracing and metric collection" -sidebar_position: 10 ---- - -# OpenTelemetry Traces and Metrics - -Access Analyzer uses OpenTelemetry (OTel) for distributed tracing. Traces are collected by the `otel-collector` pod and stored in ClickHouse, allowing you to analyze request flows and identify performance bottlenecks. - -## Architecture - -Trace data flows through the following path: - -1. Application services instrument outgoing requests and operations with OTel spans. -2. The `otel-collector` pod receives spans and exports them to ClickHouse. -3. Traces are stored in the `access_analyzer_logs` database in ClickHouse. - -## Querying Traces in ClickHouse - -**Connect to the ClickHouse pod:** - -```bash -kubectl exec -it -n access-analyzer deploy/clickhouse -- clickhouse-client -``` - -**List available tables in the trace database:** - -```bash -USE access_analyzer_logs; -SHOW TABLES; -``` - -**Query recent traces by service name:** - -```bash -SELECT TraceId, SpanName, Duration, StatusCode -FROM otel_traces -WHERE ServiceName = 'core-api' -ORDER BY Timestamp DESC -LIMIT 20; -``` - -**Find slow spans exceeding a duration threshold (in nanoseconds):** - -```bash -SELECT TraceId, SpanName, Duration -FROM otel_traces -WHERE Duration > 5000000000 -ORDER BY Duration DESC -LIMIT 10; -``` - -## Common Trace Analysis - -- **High latency requests** -- Query for spans with long durations to identify slow database queries or external API calls. -- **Error spans** -- Filter by `StatusCode` to find spans that completed with errors. -- **Cross-service tracing** -- Use a `TraceId` to follow a request across `core-api`, `connector-api`, and backing services. - -## Verifying the OTel Collector - -**Check that the collector pod is running:** - -```bash -kubectl get pods -n access-analyzer -l app=otel-collector -``` - -**View collector logs for export errors:** - -```bash -kubectl logs -n access-analyzer deploy/otel-collector --tail=50 -``` - -:::note -Trace retention depends on your ClickHouse storage configuration. Monitor disk usage on the ClickHouse pod to ensure traces are not consuming excessive storage. -::: diff --git a/docs/accessanalyzer/1.0/troubleshooting/observability/prometheus.md b/docs/accessanalyzer/1.0/troubleshooting/observability/prometheus.md deleted file mode 100644 index 253f2f8b3a..0000000000 --- a/docs/accessanalyzer/1.0/troubleshooting/observability/prometheus.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: "Prometheus Monitoring" -description: "Prometheus metrics and alerting" -sidebar_position: 20 ---- - -# Prometheus Monitoring - -Access Analyzer includes a Prometheus instance that collects metrics from application services and infrastructure components. Use Prometheus to monitor resource utilization, request rates, and application performance. - -## Accessing Prometheus - -The Prometheus pod runs in the `access-analyzer` namespace. To access the Prometheus web UI, set up a port forward: - -```bash -kubectl port-forward -n access-analyzer deploy/prometheus 9090:9090 -``` - -Then open `http://localhost:9090` in your browser. - -## Key Metrics to Monitor - -| Metric | Description | -| --- | --- | -| `container_memory_usage_bytes` | Memory consumption per container | -| `container_cpu_usage_seconds_total` | CPU usage per container | -| `http_request_duration_seconds` | Request latency histogram | -| `http_requests_total` | Total request count by status code | -| `sidekiq_queue_size` | Number of jobs waiting in each Sidekiq queue | -| `pg_stat_activity_count` | Active PostgreSQL connections | - -## Useful PromQL Queries - -**Check memory usage for Access Analyzer pods:** - -```bash -container_memory_usage_bytes{namespace="access-analyzer"} -``` - -**Calculate request error rate over the last 5 minutes:** - -```bash -rate(http_requests_total{namespace="access-analyzer", status=~"5.."}[5m]) -``` - -**Monitor Sidekiq queue depth:** - -```bash -sidekiq_queue_size{namespace="access-analyzer"} -``` - -## Recording Rules - -Access Analyzer ships with Prometheus recording rules that pre-compute frequently used metric aggregations. Recording rules reduce query latency for dashboards and alerts. View the active recording rules in the Prometheus UI under **Status > Rules**. - -## Verifying Prometheus Health - -**Confirm the Prometheus pod is running:** - -```bash -kubectl get pods -n access-analyzer -l app=prometheus -``` - -**Check Prometheus targets to ensure all scrape endpoints are reachable:** - -Open `http://localhost:9090/targets` (with port forward active) and verify all targets show an **UP** state. - -:::warning -If Prometheus targets appear as **DOWN**, verify that the target pods are running and that network policies allow traffic from the Prometheus pod on the metrics port. -::: diff --git a/docs/accessanalyzer/1.0/troubleshooting/overview.md b/docs/accessanalyzer/1.0/troubleshooting/overview.md deleted file mode 100644 index 806ed1a446..0000000000 --- a/docs/accessanalyzer/1.0/troubleshooting/overview.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: "Monitoring and Troubleshooting" -description: "Health checks, observability, and common issue resolution" -sidebar_position: 1 ---- - -# Monitoring and Troubleshooting - -This section provides guidance for monitoring the health of your Netwrix Access Analyzer deployment and resolving common issues. Use the categories below to navigate to the relevant topic. - -## Troubleshooting Categories - -| Category | Description | Link | -| --- | --- | --- | -| Health Checks | Kubernetes probes and service health endpoints | [Probes](/docs/accessanalyzer/1.0/troubleshooting/healthchecks/probes), [Endpoints](/docs/accessanalyzer/1.0/troubleshooting/healthchecks/endpoints) | -| Observability | Distributed tracing and metrics collection | [OpenTelemetry](/docs/accessanalyzer/1.0/troubleshooting/observability/opentelemetry), [Prometheus](/docs/accessanalyzer/1.0/troubleshooting/observability/prometheus) | -| Job Monitoring | Background job processing and queue health | [Sidekiq](/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/sidekiq), [Queues](/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/queues), [Failed Jobs](/docs/accessanalyzer/1.0/troubleshooting/jobmonitoring/failedjobs) | -| Common Issues | Connection failures, scan errors, and database connectivity | [Connections](/docs/accessanalyzer/1.0/troubleshooting/commonissues/connectionfailures), [Scans](/docs/accessanalyzer/1.0/troubleshooting/commonissues/scanerrors), [Database](/docs/accessanalyzer/1.0/troubleshooting/commonissues/databaseconnectivity) | - -## Quick Diagnostic Commands - -Run the following commands to get an immediate overview of system health. - -**Check all pod status across namespaces:** - -```bash -kubectl get pods -A -``` - -**View resource consumption for nodes and pods:** - -```bash -kubectl top nodes -kubectl top pods -n access-analyzer -``` - -**Check ArgoCD application sync status:** - -```bash -kubectl get apps -n argocd -``` - -**View logs for a specific pod:** - -```bash -kubectl logs -n access-analyzer --tail=100 -``` - -**Review installer and preflight logs:** - -```bash -cat /var/log/dspm-installer.log -cat /var/log/dspm-preflight.json -``` - -## Installer Exit Codes - -If installation failed, check the exit code to identify the failure category. - -| Exit Code | Meaning | -| --- | --- | -| 10 | License validation failure | -| 50 | K3s installation or startup failure | -| 60 | ArgoCD deployment failure | -| 70 | Application readiness timeout | -| 80 | Preflight check failure (CPU, memory, disk, kernel, or cgroups) | - -:::note -Most troubleshooting commands require `kubectl` access to the cluster. Ensure your kubeconfig is configured correctly before running diagnostics. -::: From 640501657a39e11de87649b674c404b1ea19b944 Mon Sep 17 00:00:00 2001 From: carlos-mejia_nwx Date: Thu, 19 Mar 2026 23:38:57 -0400 Subject: [PATCH 15/62] =?UTF-8?q?AA26:=20Complete=20documentation=20outlin?= =?UTF-8?q?e=20=E2=80=94=2010=20top-level=20sections=20with=20subsections?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restructured v1.0 docs from nested Overview into flat top-level sections: Overview, System Requirements, Connector Requirements, Installation, Start Collecting Data, Configurations, Utilizing Scanners, Dashboards, Reports, and Activity Monitor Integration. All pages contain placeholder content for outline review. Co-Authored-By: Claude Opus 4.6 --- .../_category_.json | 6 + .../activity-monitor-integration/overview.md | 9 ++ .../1.0/configurations/_category_.json | 6 + .../configuration-node/_category_.json | 6 + .../application-settings.md | 9 ++ .../configurations/configuration-node/logs.md | 9 ++ .../configuration-node/scan-executions.md | 9 ++ .../configuration-node/scans.md | 9 ++ .../configuration-node/sensitive-data.md | 9 ++ .../configuration-node/service-accounts.md | 9 ++ .../configuration-node/source-groups.md | 9 ++ .../configuration-node/sources.md | 9 ++ .../configuration-node/users.md | 9 ++ .../configurations/mip-labeling-workflow.md | 9 ++ .../source-group-changes/_category_.json | 6 + .../source-group-changes/active-directory.md | 9 ++ .../source-group-changes/entra-id.md | 9 ++ .../source-group-changes/file-server.md | 9 ++ .../source-group-changes/sharepoint-online.md | 9 ++ .../connectors/_category_.json | 2 +- .../connectors/activedirectory.md | 0 .../requirements => }/connectors/cifs.md | 0 .../1.0/connectors/entra-id/_category_.json | 6 + .../entra-id/app-registration-secret.md | 9 ++ .../connectors/entra-id/entra-requirements.md | 9 ++ .../entra-id/overview.md} | 0 .../1.0/connectors/file-servers.md | 9 ++ .../sharepoint-online/_category_.json | 6 + .../sharepoint-online/azure-permissions.md | 9 ++ .../tenant-certificate-config.md | 9 ++ .../1.0/dashboards-overview/_category_.json | 6 + .../_category_.json | 6 + .../data-security-dashboard/_category_.json | 6 + .../data-security-dashboard/activity.md | 9 ++ .../data-security-dashboard/overview.md | 9 ++ .../how-to-analyze-the-data.md | 9 ++ .../1.0/gettingstarted/_category_.json | 6 + .../gettingstarted/active-directory-sync.md | 9 ++ .../activity-data/_category_.json | 6 + .../activity-data/file-server-activity.md | 9 ++ .../1.0/gettingstarted/entra-id-sync.md | 9 ++ .../1.0/gettingstarted/file-server-scans.md | 9 ++ .../gettingstarted/first-service-account.md | 9 ++ .../gettingstarted/sharepoint-online-scan.md | 9 ++ .../1.0/gettingstarted/source-group-wizard.md | 9 ++ docs/accessanalyzer/1.0/index.md | 1 + .../{overview => }/install/_category_.json | 2 +- .../1.0/{overview => }/install/postinstall.md | 0 .../{overview => }/install/quickinstall.md | 0 .../1.0/{overview => }/install/security.md | 0 .../1.0/{overview => }/install/uninstall.md | 0 .../1.0/overview/_category_.json | 6 +- .../1.0/overview/install/dspmctl.md | 141 ---------------- .../overview/install/environmentvariables.md | 92 ----------- .../1.0/overview/install/network.md | 96 ----------- .../1.0/overview/install/overview.md | 49 ------ .../1.0/overview/install/preflight.md | 111 ------------- .../1.0/overview/install/ssl.md | 56 ------- .../1.0/overview/install/stepbystep.md | 150 ------------------ .../1.0/overview/install/upgrade.md | 77 --------- docs/accessanalyzer/1.0/overview/overview.md | 36 ----- .../1.0/overview/requirements/_category_.json | 10 -- .../requirements/connectors/localgroups.md | 52 ------ .../connectors/sharepointonline.md | 57 ------- .../requirements/database/_category_.json | 10 -- .../requirements/database/clickhouse.md | 30 ---- .../requirements/database/postgresql.md | 40 ----- .../overview/requirements/database/redis.md | 43 ----- .../1.0/overview/requirements/overview.md | 35 ---- .../overview/requirements/system/hardware.md | 84 ---------- .../1.0/reports-overview/_category_.json | 6 + .../1.0/reports-overview/access.md | 9 ++ .../1.0/reports-overview/activity.md | 9 ++ .../1.0/reports-overview/content.md | 9 ++ .../how-to-analyze-the-data.md | 9 ++ .../1.0/reports-overview/my-reports.md | 9 ++ .../1.0/reports-overview/sensitive-data.md | 9 ++ .../1.0/scanners/_category_.json | 6 + docs/accessanalyzer/1.0/scanners/overview.md | 9 ++ .../requirements => }/system/_category_.json | 2 +- .../requirements => }/system/kubernetes.md | 0 .../requirements => }/system/network.md | 0 .../install => system}/requirements.md | 0 83 files changed, 416 insertions(+), 1177 deletions(-) create mode 100644 docs/accessanalyzer/1.0/activity-monitor-integration/_category_.json create mode 100644 docs/accessanalyzer/1.0/activity-monitor-integration/overview.md create mode 100644 docs/accessanalyzer/1.0/configurations/_category_.json create mode 100644 docs/accessanalyzer/1.0/configurations/configuration-node/_category_.json create mode 100644 docs/accessanalyzer/1.0/configurations/configuration-node/application-settings.md create mode 100644 docs/accessanalyzer/1.0/configurations/configuration-node/logs.md create mode 100644 docs/accessanalyzer/1.0/configurations/configuration-node/scan-executions.md create mode 100644 docs/accessanalyzer/1.0/configurations/configuration-node/scans.md create mode 100644 docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data.md create mode 100644 docs/accessanalyzer/1.0/configurations/configuration-node/service-accounts.md create mode 100644 docs/accessanalyzer/1.0/configurations/configuration-node/source-groups.md create mode 100644 docs/accessanalyzer/1.0/configurations/configuration-node/sources.md create mode 100644 docs/accessanalyzer/1.0/configurations/configuration-node/users.md create mode 100644 docs/accessanalyzer/1.0/configurations/mip-labeling-workflow.md create mode 100644 docs/accessanalyzer/1.0/configurations/source-group-changes/_category_.json create mode 100644 docs/accessanalyzer/1.0/configurations/source-group-changes/active-directory.md create mode 100644 docs/accessanalyzer/1.0/configurations/source-group-changes/entra-id.md create mode 100644 docs/accessanalyzer/1.0/configurations/source-group-changes/file-server.md create mode 100644 docs/accessanalyzer/1.0/configurations/source-group-changes/sharepoint-online.md rename docs/accessanalyzer/1.0/{overview/requirements => }/connectors/_category_.json (88%) rename docs/accessanalyzer/1.0/{overview/requirements => }/connectors/activedirectory.md (100%) rename docs/accessanalyzer/1.0/{overview/requirements => }/connectors/cifs.md (100%) create mode 100644 docs/accessanalyzer/1.0/connectors/entra-id/_category_.json create mode 100644 docs/accessanalyzer/1.0/connectors/entra-id/app-registration-secret.md create mode 100644 docs/accessanalyzer/1.0/connectors/entra-id/entra-requirements.md rename docs/accessanalyzer/1.0/{overview/requirements/connectors/entraid.md => connectors/entra-id/overview.md} (100%) create mode 100644 docs/accessanalyzer/1.0/connectors/file-servers.md create mode 100644 docs/accessanalyzer/1.0/connectors/sharepoint-online/_category_.json create mode 100644 docs/accessanalyzer/1.0/connectors/sharepoint-online/azure-permissions.md create mode 100644 docs/accessanalyzer/1.0/connectors/sharepoint-online/tenant-certificate-config.md create mode 100644 docs/accessanalyzer/1.0/dashboards-overview/_category_.json create mode 100644 docs/accessanalyzer/1.0/dashboards-overview/active-directory-dashboard/_category_.json create mode 100644 docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/_category_.json create mode 100644 docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/activity.md create mode 100644 docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/overview.md create mode 100644 docs/accessanalyzer/1.0/dashboards-overview/how-to-analyze-the-data.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/_category_.json create mode 100644 docs/accessanalyzer/1.0/gettingstarted/active-directory-sync.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/activity-data/_category_.json create mode 100644 docs/accessanalyzer/1.0/gettingstarted/activity-data/file-server-activity.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/entra-id-sync.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/file-server-scans.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/first-service-account.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/source-group-wizard.md rename docs/accessanalyzer/1.0/{overview => }/install/_category_.json (80%) rename docs/accessanalyzer/1.0/{overview => }/install/postinstall.md (100%) rename docs/accessanalyzer/1.0/{overview => }/install/quickinstall.md (100%) rename docs/accessanalyzer/1.0/{overview => }/install/security.md (100%) rename docs/accessanalyzer/1.0/{overview => }/install/uninstall.md (100%) delete mode 100644 docs/accessanalyzer/1.0/overview/install/dspmctl.md delete mode 100644 docs/accessanalyzer/1.0/overview/install/environmentvariables.md delete mode 100644 docs/accessanalyzer/1.0/overview/install/network.md delete mode 100644 docs/accessanalyzer/1.0/overview/install/overview.md delete mode 100644 docs/accessanalyzer/1.0/overview/install/preflight.md delete mode 100644 docs/accessanalyzer/1.0/overview/install/ssl.md delete mode 100644 docs/accessanalyzer/1.0/overview/install/stepbystep.md delete mode 100644 docs/accessanalyzer/1.0/overview/install/upgrade.md delete mode 100644 docs/accessanalyzer/1.0/overview/overview.md delete mode 100644 docs/accessanalyzer/1.0/overview/requirements/_category_.json delete mode 100644 docs/accessanalyzer/1.0/overview/requirements/connectors/localgroups.md delete mode 100644 docs/accessanalyzer/1.0/overview/requirements/connectors/sharepointonline.md delete mode 100644 docs/accessanalyzer/1.0/overview/requirements/database/_category_.json delete mode 100644 docs/accessanalyzer/1.0/overview/requirements/database/clickhouse.md delete mode 100644 docs/accessanalyzer/1.0/overview/requirements/database/postgresql.md delete mode 100644 docs/accessanalyzer/1.0/overview/requirements/database/redis.md delete mode 100644 docs/accessanalyzer/1.0/overview/requirements/overview.md delete mode 100644 docs/accessanalyzer/1.0/overview/requirements/system/hardware.md create mode 100644 docs/accessanalyzer/1.0/reports-overview/_category_.json create mode 100644 docs/accessanalyzer/1.0/reports-overview/access.md create mode 100644 docs/accessanalyzer/1.0/reports-overview/activity.md create mode 100644 docs/accessanalyzer/1.0/reports-overview/content.md create mode 100644 docs/accessanalyzer/1.0/reports-overview/how-to-analyze-the-data.md create mode 100644 docs/accessanalyzer/1.0/reports-overview/my-reports.md create mode 100644 docs/accessanalyzer/1.0/reports-overview/sensitive-data.md create mode 100644 docs/accessanalyzer/1.0/scanners/_category_.json create mode 100644 docs/accessanalyzer/1.0/scanners/overview.md rename docs/accessanalyzer/1.0/{overview/requirements => }/system/_category_.json (88%) rename docs/accessanalyzer/1.0/{overview/requirements => }/system/kubernetes.md (100%) rename docs/accessanalyzer/1.0/{overview/requirements => }/system/network.md (100%) rename docs/accessanalyzer/1.0/{overview/install => system}/requirements.md (100%) diff --git a/docs/accessanalyzer/1.0/activity-monitor-integration/_category_.json b/docs/accessanalyzer/1.0/activity-monitor-integration/_category_.json new file mode 100644 index 0000000000..463f554a78 --- /dev/null +++ b/docs/accessanalyzer/1.0/activity-monitor-integration/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Setting up Activity Monitor Integration", + "position": 70, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/activity-monitor-integration/overview.md b/docs/accessanalyzer/1.0/activity-monitor-integration/overview.md new file mode 100644 index 0000000000..21dd6869e7 --- /dev/null +++ b/docs/accessanalyzer/1.0/activity-monitor-integration/overview.md @@ -0,0 +1,9 @@ +--- +title: "Setting up Activity Monitor Integration" +description: "Configure Activity Monitor integration with Access Analyzer" +sidebar_position: 10 +--- + +# Setting up Activity Monitor Integration + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/_category_.json b/docs/accessanalyzer/1.0/configurations/_category_.json new file mode 100644 index 0000000000..9b86fef70b --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Configurations and Making Changes", + "position": 30, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/_category_.json b/docs/accessanalyzer/1.0/configurations/configuration-node/_category_.json new file mode 100644 index 0000000000..d5bca8fd28 --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Configuration Node", + "position": 20, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/application-settings.md b/docs/accessanalyzer/1.0/configurations/configuration-node/application-settings.md new file mode 100644 index 0000000000..3aba566106 --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/application-settings.md @@ -0,0 +1,9 @@ +--- +title: "Application Settings" +description: "Managing application settings in the Configuration node" +sidebar_position: 60 +--- + +# Application Settings + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/logs.md b/docs/accessanalyzer/1.0/configurations/configuration-node/logs.md new file mode 100644 index 0000000000..b28fd89fbe --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/logs.md @@ -0,0 +1,9 @@ +--- +title: "Logs" +description: "Viewing logs in the Configuration node" +sidebar_position: 70 +--- + +# Logs + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/scan-executions.md b/docs/accessanalyzer/1.0/configurations/configuration-node/scan-executions.md new file mode 100644 index 0000000000..d2f01e283b --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/scan-executions.md @@ -0,0 +1,9 @@ +--- +title: "Scan Executions" +description: "Viewing scan execution history in the Configuration node" +sidebar_position: 40 +--- + +# Scan Executions + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/scans.md b/docs/accessanalyzer/1.0/configurations/configuration-node/scans.md new file mode 100644 index 0000000000..0f21da4b92 --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/scans.md @@ -0,0 +1,9 @@ +--- +title: "Scans" +description: "Managing scans in the Configuration node" +sidebar_position: 30 +--- + +# Scans + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data.md b/docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data.md new file mode 100644 index 0000000000..5c5453e455 --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data.md @@ -0,0 +1,9 @@ +--- +title: "Sensitive Data" +description: "Managing sensitive data settings in the Configuration node" +sidebar_position: 55 +--- + +# Sensitive Data + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/service-accounts.md b/docs/accessanalyzer/1.0/configurations/configuration-node/service-accounts.md new file mode 100644 index 0000000000..7ce3e52660 --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/service-accounts.md @@ -0,0 +1,9 @@ +--- +title: "Service Accounts" +description: "Managing service accounts in the Configuration node" +sidebar_position: 20 +--- + +# Service Accounts + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/source-groups.md b/docs/accessanalyzer/1.0/configurations/configuration-node/source-groups.md new file mode 100644 index 0000000000..d78d64468a --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/source-groups.md @@ -0,0 +1,9 @@ +--- +title: "Source Groups" +description: "Managing source groups in the Configuration node" +sidebar_position: 80 +--- + +# Source Groups + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/sources.md b/docs/accessanalyzer/1.0/configurations/configuration-node/sources.md new file mode 100644 index 0000000000..f99a43aef2 --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/sources.md @@ -0,0 +1,9 @@ +--- +title: "Sources" +description: "Managing sources in the Configuration node" +sidebar_position: 10 +--- + +# Sources + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/users.md b/docs/accessanalyzer/1.0/configurations/configuration-node/users.md new file mode 100644 index 0000000000..c5a0e8191a --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/users.md @@ -0,0 +1,9 @@ +--- +title: "Users" +description: "Managing users in the Configuration node" +sidebar_position: 50 +--- + +# Users + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/mip-labeling-workflow.md b/docs/accessanalyzer/1.0/configurations/mip-labeling-workflow.md new file mode 100644 index 0000000000..b28cbd75aa --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/mip-labeling-workflow.md @@ -0,0 +1,9 @@ +--- +title: "MIP Labeling and Workflow" +description: "Microsoft Information Protection labeling and workflow configuration" +sidebar_position: 30 +--- + +# MIP Labeling and Workflow + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/source-group-changes/_category_.json b/docs/accessanalyzer/1.0/configurations/source-group-changes/_category_.json new file mode 100644 index 0000000000..0b5c8adf0b --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/source-group-changes/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Making Changes to Source Group Wizards", + "position": 10, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/configurations/source-group-changes/active-directory.md b/docs/accessanalyzer/1.0/configurations/source-group-changes/active-directory.md new file mode 100644 index 0000000000..f723d5e4a8 --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/source-group-changes/active-directory.md @@ -0,0 +1,9 @@ +--- +title: "Active Directory Source Group" +description: "Making changes to an Active Directory source group wizard workflow" +sidebar_position: 10 +--- + +# Active Directory Source Group + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/source-group-changes/entra-id.md b/docs/accessanalyzer/1.0/configurations/source-group-changes/entra-id.md new file mode 100644 index 0000000000..787bb89c41 --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/source-group-changes/entra-id.md @@ -0,0 +1,9 @@ +--- +title: "Entra ID Source Group" +description: "Making changes to an Entra ID source group wizard workflow" +sidebar_position: 30 +--- + +# Entra ID Source Group + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/source-group-changes/file-server.md b/docs/accessanalyzer/1.0/configurations/source-group-changes/file-server.md new file mode 100644 index 0000000000..7186761125 --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/source-group-changes/file-server.md @@ -0,0 +1,9 @@ +--- +title: "File Server Source Group" +description: "Making changes to a File Server source group wizard workflow" +sidebar_position: 20 +--- + +# File Server Source Group + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/source-group-changes/sharepoint-online.md b/docs/accessanalyzer/1.0/configurations/source-group-changes/sharepoint-online.md new file mode 100644 index 0000000000..0b81d403ff --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/source-group-changes/sharepoint-online.md @@ -0,0 +1,9 @@ +--- +title: "SharePoint Online Source Group" +description: "Making changes to a SharePoint Online source group wizard workflow" +sidebar_position: 40 +--- + +# SharePoint Online Source Group + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/overview/requirements/connectors/_category_.json b/docs/accessanalyzer/1.0/connectors/_category_.json similarity index 88% rename from docs/accessanalyzer/1.0/overview/requirements/connectors/_category_.json rename to docs/accessanalyzer/1.0/connectors/_category_.json index 4616c42c8c..4ebd7ecb5d 100644 --- a/docs/accessanalyzer/1.0/overview/requirements/connectors/_category_.json +++ b/docs/accessanalyzer/1.0/connectors/_category_.json @@ -1,6 +1,6 @@ { "label": "Connector Requirements", - "position": 30, + "position": 14, "collapsed": true, "collapsible": true, "link": { diff --git a/docs/accessanalyzer/1.0/overview/requirements/connectors/activedirectory.md b/docs/accessanalyzer/1.0/connectors/activedirectory.md similarity index 100% rename from docs/accessanalyzer/1.0/overview/requirements/connectors/activedirectory.md rename to docs/accessanalyzer/1.0/connectors/activedirectory.md diff --git a/docs/accessanalyzer/1.0/overview/requirements/connectors/cifs.md b/docs/accessanalyzer/1.0/connectors/cifs.md similarity index 100% rename from docs/accessanalyzer/1.0/overview/requirements/connectors/cifs.md rename to docs/accessanalyzer/1.0/connectors/cifs.md diff --git a/docs/accessanalyzer/1.0/connectors/entra-id/_category_.json b/docs/accessanalyzer/1.0/connectors/entra-id/_category_.json new file mode 100644 index 0000000000..83c1bf103d --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/entra-id/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Entra ID", + "position": 30, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/connectors/entra-id/app-registration-secret.md b/docs/accessanalyzer/1.0/connectors/entra-id/app-registration-secret.md new file mode 100644 index 0000000000..789a141560 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/entra-id/app-registration-secret.md @@ -0,0 +1,9 @@ +--- +title: "App Registration / Secret Configuration" +description: "Configure app registration and client secret for Entra ID" +sidebar_position: 30 +--- + +# App Registration / Secret Configuration + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/connectors/entra-id/entra-requirements.md b/docs/accessanalyzer/1.0/connectors/entra-id/entra-requirements.md new file mode 100644 index 0000000000..b2b3c7917a --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/entra-id/entra-requirements.md @@ -0,0 +1,9 @@ +--- +title: "Setting Up Requirements Within Entra" +description: "Configure Entra ID requirements for connectivity" +sidebar_position: 20 +--- + +# Setting Up Requirements Within Entra + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/overview/requirements/connectors/entraid.md b/docs/accessanalyzer/1.0/connectors/entra-id/overview.md similarity index 100% rename from docs/accessanalyzer/1.0/overview/requirements/connectors/entraid.md rename to docs/accessanalyzer/1.0/connectors/entra-id/overview.md diff --git a/docs/accessanalyzer/1.0/connectors/file-servers.md b/docs/accessanalyzer/1.0/connectors/file-servers.md new file mode 100644 index 0000000000..a70313521e --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/file-servers.md @@ -0,0 +1,9 @@ +--- +title: "File Servers" +description: "File server connector requirements for Access Analyzer" +sidebar_position: 20 +--- + +# File Servers + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/connectors/sharepoint-online/_category_.json b/docs/accessanalyzer/1.0/connectors/sharepoint-online/_category_.json new file mode 100644 index 0000000000..a8d05dd13b --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/sharepoint-online/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "SharePoint Online", + "position": 50, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/connectors/sharepoint-online/azure-permissions.md b/docs/accessanalyzer/1.0/connectors/sharepoint-online/azure-permissions.md new file mode 100644 index 0000000000..da88304a7a --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/sharepoint-online/azure-permissions.md @@ -0,0 +1,9 @@ +--- +title: "Setting Up Requirements Within Entra" +description: "Configure Entra ID requirements for SharePoint Online connectivity" +sidebar_position: 10 +--- + +# Setting Up Requirements Within Entra + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/connectors/sharepoint-online/tenant-certificate-config.md b/docs/accessanalyzer/1.0/connectors/sharepoint-online/tenant-certificate-config.md new file mode 100644 index 0000000000..b702b388e5 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/sharepoint-online/tenant-certificate-config.md @@ -0,0 +1,9 @@ +--- +title: "App Registration / Certificate Configuration" +description: "Configure app registration and certificate authentication for SharePoint Online" +sidebar_position: 20 +--- + +# App Registration / Certificate Configuration + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/dashboards-overview/_category_.json b/docs/accessanalyzer/1.0/dashboards-overview/_category_.json new file mode 100644 index 0000000000..2ce5a39907 --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards-overview/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Dashboards Overview", + "position": 50, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/dashboards-overview/active-directory-dashboard/_category_.json b/docs/accessanalyzer/1.0/dashboards-overview/active-directory-dashboard/_category_.json new file mode 100644 index 0000000000..527eda587f --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards-overview/active-directory-dashboard/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Active Directory Dashboard", + "position": 30, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/_category_.json b/docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/_category_.json new file mode 100644 index 0000000000..d27cd7ee77 --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Data Security Dashboard", + "position": 20, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/activity.md b/docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/activity.md new file mode 100644 index 0000000000..cd6072b460 --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/activity.md @@ -0,0 +1,9 @@ +--- +title: "Activity" +description: "Activity view in the Data Security Dashboard" +sidebar_position: 20 +--- + +# Activity + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/overview.md b/docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/overview.md new file mode 100644 index 0000000000..c6d4d8bd09 --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/overview.md @@ -0,0 +1,9 @@ +--- +title: "Overview" +description: "Overview of the Data Security Dashboard" +sidebar_position: 10 +--- + +# Overview + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/dashboards-overview/how-to-analyze-the-data.md b/docs/accessanalyzer/1.0/dashboards-overview/how-to-analyze-the-data.md new file mode 100644 index 0000000000..dfb66b947e --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards-overview/how-to-analyze-the-data.md @@ -0,0 +1,9 @@ +--- +title: "How to Analyze the Data" +description: "Learn how to analyze data presented in dashboards" +sidebar_position: 10 +--- + +# How to Analyze the Data + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/gettingstarted/_category_.json b/docs/accessanalyzer/1.0/gettingstarted/_category_.json new file mode 100644 index 0000000000..1c9c947f1d --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Start Collecting Data", + "position": 20, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/gettingstarted/active-directory-sync.md b/docs/accessanalyzer/1.0/gettingstarted/active-directory-sync.md new file mode 100644 index 0000000000..55ac39164a --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/active-directory-sync.md @@ -0,0 +1,9 @@ +--- +title: "Setting Up My First Active Directory Sync" +description: "Connect to Active Directory and sync users, groups, and organizational units" +sidebar_position: 20 +--- + +# Setting Up My First Active Directory Sync + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/gettingstarted/activity-data/_category_.json b/docs/accessanalyzer/1.0/gettingstarted/activity-data/_category_.json new file mode 100644 index 0000000000..188fff07b8 --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/activity-data/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Start Collecting Activity Data", + "position": 70, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/gettingstarted/activity-data/file-server-activity.md b/docs/accessanalyzer/1.0/gettingstarted/activity-data/file-server-activity.md new file mode 100644 index 0000000000..41114e0caa --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/activity-data/file-server-activity.md @@ -0,0 +1,9 @@ +--- +title: "File Server Activity" +description: "Start collecting file server activity data" +sidebar_position: 10 +--- + +# File Server Activity + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/gettingstarted/entra-id-sync.md b/docs/accessanalyzer/1.0/gettingstarted/entra-id-sync.md new file mode 100644 index 0000000000..031773a286 --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/entra-id-sync.md @@ -0,0 +1,9 @@ +--- +title: "Setting Up My First Entra ID Sync" +description: "Connect to Microsoft Entra ID and sync cloud identities" +sidebar_position: 40 +--- + +# Setting Up My First Entra ID Sync + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/gettingstarted/file-server-scans.md b/docs/accessanalyzer/1.0/gettingstarted/file-server-scans.md new file mode 100644 index 0000000000..e99a39cb05 --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/file-server-scans.md @@ -0,0 +1,9 @@ +--- +title: "Setting Up My First File Server Scans" +description: "Scan CIFS/SMB file shares for permissions and sensitive data" +sidebar_position: 30 +--- + +# Setting Up My First File Server Scans + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/gettingstarted/first-service-account.md b/docs/accessanalyzer/1.0/gettingstarted/first-service-account.md new file mode 100644 index 0000000000..124d4ff6bb --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/first-service-account.md @@ -0,0 +1,9 @@ +--- +title: "Setting Up My First Service Account" +description: "Create your first service account to connect to data sources" +sidebar_position: 1 +--- + +# Setting Up My First Service Account + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan.md b/docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan.md new file mode 100644 index 0000000000..e831c710c1 --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan.md @@ -0,0 +1,9 @@ +--- +title: "Setting Up My First SharePoint Online Scan" +description: "Scan SharePoint Online sites for permissions and sensitive data" +sidebar_position: 50 +--- + +# Setting Up My First SharePoint Online Scan + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/gettingstarted/source-group-wizard.md b/docs/accessanalyzer/1.0/gettingstarted/source-group-wizard.md new file mode 100644 index 0000000000..a78450039d --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/source-group-wizard.md @@ -0,0 +1,9 @@ +--- +title: "Understanding the Source Group Wizard Workflow" +description: "Learn how the Source Group Wizard guides you through connecting data sources and configuring scans" +sidebar_position: 10 +--- + +# Understanding the Source Group Wizard Workflow + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/index.md b/docs/accessanalyzer/1.0/index.md index 854bbb7dbe..f9ad0c684b 100644 --- a/docs/accessanalyzer/1.0/index.md +++ b/docs/accessanalyzer/1.0/index.md @@ -18,3 +18,4 @@ Netwrix Access Analyzer is an on-premises Data Security Posture Management (DSPM ## Documentation Sections - [Overview](overview/overview) — Introduction to the product, key concepts, requirements, and installation +- [Getting Started](gettingstarted/overview) — Step-by-step guides for your first scans and syncs diff --git a/docs/accessanalyzer/1.0/overview/install/_category_.json b/docs/accessanalyzer/1.0/install/_category_.json similarity index 80% rename from docs/accessanalyzer/1.0/overview/install/_category_.json rename to docs/accessanalyzer/1.0/install/_category_.json index f5134e8f2b..edb97672cd 100644 --- a/docs/accessanalyzer/1.0/overview/install/_category_.json +++ b/docs/accessanalyzer/1.0/install/_category_.json @@ -1,6 +1,6 @@ { "label": "Installation", - "position": 40, + "position": 16, "collapsed": true, "collapsible": true } diff --git a/docs/accessanalyzer/1.0/overview/install/postinstall.md b/docs/accessanalyzer/1.0/install/postinstall.md similarity index 100% rename from docs/accessanalyzer/1.0/overview/install/postinstall.md rename to docs/accessanalyzer/1.0/install/postinstall.md diff --git a/docs/accessanalyzer/1.0/overview/install/quickinstall.md b/docs/accessanalyzer/1.0/install/quickinstall.md similarity index 100% rename from docs/accessanalyzer/1.0/overview/install/quickinstall.md rename to docs/accessanalyzer/1.0/install/quickinstall.md diff --git a/docs/accessanalyzer/1.0/overview/install/security.md b/docs/accessanalyzer/1.0/install/security.md similarity index 100% rename from docs/accessanalyzer/1.0/overview/install/security.md rename to docs/accessanalyzer/1.0/install/security.md diff --git a/docs/accessanalyzer/1.0/overview/install/uninstall.md b/docs/accessanalyzer/1.0/install/uninstall.md similarity index 100% rename from docs/accessanalyzer/1.0/overview/install/uninstall.md rename to docs/accessanalyzer/1.0/install/uninstall.md diff --git a/docs/accessanalyzer/1.0/overview/_category_.json b/docs/accessanalyzer/1.0/overview/_category_.json index 5015c8e965..e030b69dcf 100644 --- a/docs/accessanalyzer/1.0/overview/_category_.json +++ b/docs/accessanalyzer/1.0/overview/_category_.json @@ -2,9 +2,5 @@ "label": "Overview", "position": 10, "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } + "collapsible": true } diff --git a/docs/accessanalyzer/1.0/overview/install/dspmctl.md b/docs/accessanalyzer/1.0/overview/install/dspmctl.md deleted file mode 100644 index 7bdc4cc594..0000000000 --- a/docs/accessanalyzer/1.0/overview/install/dspmctl.md +++ /dev/null @@ -1,141 +0,0 @@ ---- -title: "DSPMctl CLI" -description: "Command-line reference for the DSPMctl application management tool" -sidebar_position: 45 ---- - -# DSPMctl CLI - -DSPMctl is a command-line tool installed by the Access Analyzer installer at `/usr/local/bin/dspmctl`. It provides convenient commands for managing ArgoCD-deployed applications without requiring direct `kubectl` or ArgoCD CLI interaction. - -## Commands - -### auto-status - -Display the current sync and auto-sync status of all applications: - -```bash -dspmctl auto-status -``` - -### enable-auto - -Enable auto-sync for a specific application. When auto-sync is enabled, ArgoCD automatically applies changes when the target revision is updated in the OCI registry: - -```bash -dspmctl enable-auto -``` - -**Example:** - -```bash -dspmctl enable-auto netwrix.core-api -``` - -### disable-auto - -Disable auto-sync for a specific application: - -```bash -dspmctl disable-auto -``` - -### set-revision - -Update the target revision (version) for an application or application set: - -```bash -dspmctl set-revision -``` - -**Example:** - -```bash -dspmctl set-revision netwrix 1.0.6 -``` - -### sync - -Manually trigger a sync for a specific application: - -```bash -dspmctl sync -``` - -**Example:** - -```bash -dspmctl sync netwrix.core-api -``` - -### set-helm-param - -Set one or more Helm parameter overrides for an application: - -```bash -dspmctl set-helm-param -dspmctl set-helm-param = [= ...] -``` - -**Examples:** - -```bash -# Set a single parameter -dspmctl set-helm-param netwrix.core-api image.tag v1.2.3 - -# Set multiple parameters -dspmctl set-helm-param netwrix.core-api image.tag=v1.2.3 replicaCount=2 -``` - -### version - -Display the DSPMctl version: - -```bash -dspmctl version -``` - -### help - -Display usage information: - -```bash -dspmctl --help -``` - -## Common Workflows - -### Upgrading to a New Version - -To update all applications to a new target revision: - -```bash -# Set the new version -dspmctl set-revision netwrix 1.0.7 - -# Verify applications are syncing -dspmctl auto-status - -# Force sync if needed -dspmctl sync netwrix.infra -dspmctl sync netwrix.core-api -``` - -See [Upgrading Access Analyzer](/docs/accessanalyzer/1_0/install/upgrade) for the full upgrade procedure. - -### Scaling an Application - -```bash -dspmctl set-helm-param netwrix.core-api replicaCount 3 -``` - -### Checking Deployment Health - -```bash -# Check auto-sync status -dspmctl auto-status - -# Also verify with kubectl -kubectl get apps -n argocd -kubectl get pods -n access-analyzer -``` diff --git a/docs/accessanalyzer/1.0/overview/install/environmentvariables.md b/docs/accessanalyzer/1.0/overview/install/environmentvariables.md deleted file mode 100644 index 5b2cbb6d90..0000000000 --- a/docs/accessanalyzer/1.0/overview/install/environmentvariables.md +++ /dev/null @@ -1,92 +0,0 @@ ---- -title: "Environment Variables" -description: "CLI flags and environment variable reference for the Access Analyzer installer" -sidebar_position: 30 ---- - -# Environment Variables - -The Access Analyzer installer can be configured using command-line flags or environment variables. Environment variables are useful for scripted or automated installations. - -## CLI Flags - -``` -install.sh --license-key [options] - -Options: - --license-key Netwrix license key (required) - --target-revision Application version to deploy (default: 1.*) - --size Resource size multiplier, 1–10 (default: 1) - --accept-warnings Accept preflight warnings and continue - --dry-run Run preflight checks only, without installing - --help Display usage information -``` - -## Mandatory Variables - -| Variable | CLI Flag | Description | -| --- | --- | --- | -| `LICENSE_KEY` | `--license-key` | Netwrix license key for OCI registry authentication. Required for installation. | - -## Optional Configuration Variables - -| Variable | CLI Flag | Default | Description | -| --- | --- | --- | --- | -| `DSPM_TARGET_REVISION` | `--target-revision` | `1.*` | Target version for DSPM applications | -| `SIZE` | `--size` | `1` | Resource size multiplier (1–10). Scales memory thresholds. | -| `ACCEPT_WARNINGS` | `--accept-warnings` | `false` | Set to `true` to skip preflight warning prompts | - -## Proxy Variables - -| Variable | Description | Example | -| --- | --- | --- | -| `HTTP_PROXY` | HTTP proxy server URL | `http://proxy.example.com:8080` | -| `HTTPS_PROXY` | HTTPS proxy server URL | `http://proxy.example.com:8080` | -| `NO_PROXY` | Comma-separated list of hosts to bypass proxy | `localhost,127.0.0.1,10.0.0.0/8` | - -## Advanced Variables - -These variables are intended for specialized deployments and troubleshooting. They are not required for standard installations. - -| Variable | Default | Description | -| --- | --- | --- | -| `SKIP_AV_CHECK` | `false` | Skip antivirus detection during preflight | -| `FORCE_CA_MOUNT` | `false` | Force CA certificate bundle mounting to ArgoCD components | -| `USE_LOCAL_CHARTS` | `false` | Use local Helm charts instead of OCI registry | -| `USE_MIRRORED_IMAGES` | `true` | Use mirrored container images | -| `DISABLE_DEX` | `true` | Disable the Dex identity provider in ArgoCD | -| `DISABLE_NOTIFICATIONS` | `true` | Disable ArgoCD notifications | -| `DSPM_INSTALL_DEBUG` | Not set | Enable debug logging for the installer | - -## Examples - -**Basic installation:** - -```bash -export LICENSE_KEY='' -curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash - -``` - -**Installation with a specific version:** - -```bash -export LICENSE_KEY='' -curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- --target-revision "1.0.6" -``` - -**Scaled deployment (2x resources):** - -```bash -export LICENSE_KEY='' -curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- --size 2 -``` - -**Installation behind a proxy:** - -```bash -export LICENSE_KEY='' -export HTTP_PROXY="http://proxy.example.com:8080" -export HTTPS_PROXY="http://proxy.example.com:8080" -export NO_PROXY="localhost,127.0.0.1" -curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash - -``` diff --git a/docs/accessanalyzer/1.0/overview/install/network.md b/docs/accessanalyzer/1.0/overview/install/network.md deleted file mode 100644 index 8e188d3da6..0000000000 --- a/docs/accessanalyzer/1.0/overview/install/network.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: "Network Configuration" -description: "Network requirements, outbound endpoints, and firewall rules for Access Analyzer" -sidebar_position: 20 ---- - -# Network Configuration - -Access Analyzer requires outbound HTTPS connectivity during installation to download Kubernetes components, container images, and application packages. This page lists the required endpoints and provides firewall configuration examples. - -## Required Outbound Endpoints - -The following endpoints must be reachable over HTTPS (port 443) from the Access Analyzer VM: - -| Endpoint | Purpose | -| --- | --- | -| `get.k3s.io` | K3s installer download | -| `raw.githubusercontent.com` | ArgoCD manifests (bootstrap only) | -| `oci.pkg.keygen.sh` | Netwrix OCI registry — Helm charts and application images | -| `docker.io` / `docker.com` | Container base images (PostgreSQL, ClickHouse, Redis) | - -:::note -All application packages are distributed through the Netwrix OCI registry at `oci.pkg.keygen.sh`. Access is authenticated with your license key. No external Git repository access is required. -::: - -## Firewall Rules - -### Azure VMs (Network Security Group) - -```bash -az network nsg rule create \ - --resource-group \ - --nsg-name \ - --name AllowHTTPSOutbound \ - --protocol Tcp \ - --priority 1010 \ - --destination-port-range 443 \ - --direction Outbound \ - --access Allow -``` - -### AWS EC2 (Security Groups) - -```bash -aws ec2 authorize-security-group-egress \ - --group-id \ - --protocol tcp \ - --port 443 \ - --cidr 0.0.0.0/0 -``` - -### On-Premises / Bare Metal - -Using `ufw` (Ubuntu Firewall): - -```bash -sudo ufw allow out 443/tcp -``` - -Using `iptables`: - -```bash -sudo iptables -A OUTPUT -p tcp --dport 443 -j ACCEPT -``` - -## Proxy Configuration - -If your environment routes outbound traffic through a proxy server, set the following environment variables before running the installer: - -```bash -export HTTP_PROXY="http://:" -export HTTPS_PROXY="http://:" -export NO_PROXY="localhost,127.0.0.1,10.0.0.0/8" -``` - -See [Environment Variables](/docs/accessanalyzer/1_0/install/environmentvariables) for the full list of proxy-related variables. - -## Verifying Connectivity - -Test outbound access to the required endpoints before installation: - -```bash -# Test K3s installer access -curl -I https://get.k3s.io - -# Test Netwrix registry access -curl -I https://oci.pkg.keygen.sh:443 -``` - -## Common Network Issues - -| Issue | Symptom | Solution | -| --- | --- | --- | -| Applications not syncing | `connection refused` to Keygen | Verify outbound HTTPS (443) to `oci.pkg.keygen.sh` | -| K3s installation fails | Download errors | Check connectivity to `get.k3s.io` | -| Container image pull failures | `ImagePullBackOff` pod status | Verify access to `oci.pkg.keygen.sh` and license key validity | diff --git a/docs/accessanalyzer/1.0/overview/install/overview.md b/docs/accessanalyzer/1.0/overview/install/overview.md deleted file mode 100644 index af5712a7a3..0000000000 --- a/docs/accessanalyzer/1.0/overview/install/overview.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: "Installation" -description: "Installation and deployment overview for Netwrix Access Analyzer" -sidebar_position: 1 ---- - -# Installation - -Netwrix Access Analyzer is deployed as a self-contained Kubernetes cluster on a single Linux virtual machine. The automated installer provisions all required infrastructure components — including K3s, ArgoCD, databases, and application services — with a single command. - -## Installation Paths - -Choose the installation path that best fits your needs: - -| Path | Description | Audience | -| --- | --- | --- | -| [Quick Install](/docs/accessanalyzer/1_0/install/quickinstall) | Single-page guide to get Access Analyzer running fast | Experienced Linux admins | -| [Step-by-Step Install](/docs/accessanalyzer/1_0/install/stepbystep) | Detailed walkthrough with explanations for each phase | First-time installers | - -## Before You Begin - -Review the following requirements before starting installation: - -- [Hardware and System Requirements](/docs/accessanalyzer/1_0/install/requirements) — CPU, memory, disk, OS, and virtualization -- [Network Configuration](/docs/accessanalyzer/1_0/install/network) — Outbound endpoints and firewall rules -- [Preflight Checks](/docs/accessanalyzer/1_0/install/preflight) — Automated system validation and dry-run mode - -## What the Installer Does - -The installer automates the entire deployment in approximately 15–30 minutes: - -1. **Validates prerequisites** — Runs preflight checks for hardware, OS, and network -2. **Deploys K3s** — Installs a lightweight Kubernetes distribution (v1.33.4) with secrets-at-rest encryption -3. **Installs ArgoCD** — Sets up GitOps-based application lifecycle management (v3.2.0) -4. **Deploys applications** — Pulls Helm charts from the Netwrix OCI registry and deploys all services -5. **Verifies health** — Monitors application health until all components are operational - -## After Installation - -- [Post-Installation Validation](/docs/accessanalyzer/1_0/install/postinstall) — Verify cluster health and access the ArgoCD UI -- [SSL / TLS Configuration](/docs/accessanalyzer/1_0/install/ssl) — Certificate auto-detection and custom CA bundles -- [DSPMctl CLI](/docs/accessanalyzer/1_0/install/dspmctl) — Manage applications with the built-in command-line tool - -## Additional Topics - -- [Environment Variables](/docs/accessanalyzer/1_0/install/environmentvariables) — CLI flags and environment variable reference -- [Upgrading Access Analyzer](/docs/accessanalyzer/1_0/install/upgrade) — Update to a new version -- [Uninstalling Access Analyzer](/docs/accessanalyzer/1_0/install/uninstall) — Remove the installation -- [Security Best Practices](/docs/accessanalyzer/1_0/install/security) — Harden your deployment diff --git a/docs/accessanalyzer/1.0/overview/install/preflight.md b/docs/accessanalyzer/1.0/overview/install/preflight.md deleted file mode 100644 index 6ac77af940..0000000000 --- a/docs/accessanalyzer/1.0/overview/install/preflight.md +++ /dev/null @@ -1,111 +0,0 @@ ---- -title: "Preflight Checks" -description: "System validation checks performed before installation" -sidebar_position: 25 ---- - -# Preflight Checks - -The Access Analyzer installer performs comprehensive system validation before any installation steps begin. Preflight checks verify hardware resources, kernel capabilities, and system access to prevent partial installation failures. - -## Dry-Run Mode - -Run preflight checks without installing anything using the `--dry-run` flag: - -```bash -export LICENSE_KEY='' -curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- --dry-run -``` - -Dry-run mode performs all validation checks and writes results to `/var/log/dspm-preflight.json`, then exits without modifying the system. - -## Phase 1: System Resource Validation - -| Check | Minimum | Recommended | Failure Behavior | -| --- | --- | --- | --- | -| **Total memory** | 8 GB | 16 GB | FAIL — installation blocked | -| **Available memory** | 4 GB (during install) | — | FAIL — installation blocked | -| **CPU cores** | 2 vCPUs | 4 vCPUs | FAIL — installation blocked | -| **Disk space (`/`, `/var`, `/var/lib`)** | 20 GB free | 50 GB free | FAIL — installation blocked | -| **Disk space (`/var/log`)** | 5 GB free | — | FAIL — installation blocked | -| **Disk space (`/etc`)** | 1 GB free | — | FAIL — installation blocked | -| **Write access** | `/var`, `/tmp`, `/etc` | — | FAIL — installation blocked | -| **Swap** | None required | 2–4 GB if RAM < 16 GB | WARN — continues with warning | -| **Dynamic memory** | N/A | Static allocation | WARN — continues with warning | - -## Phase 2: Kernel and System Access - -| Check | Requirement | Failure Behavior | -| --- | --- | --- | -| **System directories** | Write access to `/var` and `/etc` | FAIL — installation blocked | -| **Kernel modules** | `/proc/modules` readable | FAIL — installation blocked | -| **Control groups** | cgroups v1 or v2 with memory and CPU controllers | FAIL — installation blocked | -| **Overlay filesystem** | `overlay` kernel module loaded or available | FAIL — installation blocked | -| **Linux namespaces** | NET, PID, IPC, UTS, MNT, USER | FAIL — installation blocked | - -## Antivirus Detection - -The installer scans for active antivirus agents that may interfere with Kubernetes container operations: - -- Microsoft Defender for Endpoint (mdatp) -- CrowdStrike Falcon -- ClamAV -- Sophos -- Carbon Black -- Trend Micro - -If an antivirus agent is detected, the installer issues a warning. To skip this check, set the `SKIP_AV_CHECK` environment variable: - -```bash -export SKIP_AV_CHECK=true -``` - -## Preflight Result Log - -All preflight results are written to `/var/log/dspm-preflight.json` in structured JSON format: - -```json -{ - "timestamp": "2026-01-15T10:30:00Z", - "overall_status": "PASS", - "thresholds": { - "min_ram_gb": 8, - "min_cpu_cores": 2, - "min_disk_gb": 20 - }, - "checks": [ - { - "status": "PASS", - "component": "Memory", - "message": "Total memory sufficient for DSPM installation", - "current_value": "15.56 GB", - "threshold": "8 GB minimum" - } - ] -} -``` - -## Handling Warnings - -When preflight checks produce warnings (but no failures), the installer prompts for confirmation before proceeding. To automatically accept warnings — for example, in automated or scripted deployments — use one of the following: - -```bash -# CLI flag -curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- --accept-warnings - -# Environment variable -export ACCEPT_WARNINGS=true -``` - -## Exit Codes - -The installer uses specific exit codes to indicate failure categories: - -| Exit Code | Meaning | -| --- | --- | -| `0` | Success | -| `10` | License validation error | -| `50` | K3s installation error | -| `60` | ArgoCD installation error | -| `70` | Application deployment timeout | -| `80` | Preflight check failure | diff --git a/docs/accessanalyzer/1.0/overview/install/ssl.md b/docs/accessanalyzer/1.0/overview/install/ssl.md deleted file mode 100644 index cebd210517..0000000000 --- a/docs/accessanalyzer/1.0/overview/install/ssl.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: "SSL / TLS Configuration" -description: "Certificate auto-detection and custom CA bundle configuration for Access Analyzer" -sidebar_position: 60 ---- - -# SSL / TLS Configuration - -Access Analyzer uses HTTPS for all client-facing traffic, served through Traefik as the ingress controller. By default, a self-signed TLS certificate is generated during installation. This page covers certificate handling and custom CA bundle configuration. - -## Default Behavior - -After installation, Access Analyzer is accessible at `https://`. The default self-signed certificate causes browsers to display a security warning on first access. - -## Certificate Auto-Detection - -During installation, the installer scans for existing CA certificate bundles on the system. If a bundle is found, it is automatically mounted into ArgoCD components to enable TLS verification for outbound connections to the OCI registry and other external services. - -The installer searches the following paths: - -| Path | Description | -| --- | --- | -| `/etc/ssl/certs/ca-certificates.crt` | Debian/Ubuntu CA bundle | -| `/etc/pki/tls/certs/ca-bundle.crt` | RHEL/CentOS CA bundle | -| `/etc/ssl/ca-bundle.pem` | SUSE CA bundle | -| `/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem` | RHEL trust store | -| `/etc/ssl/cert.pem` | Alpine/macOS CA bundle | -| `/usr/local/share/ca-certificates/` | Custom CA directory | - -## Forcing CA Bundle Mounting - -If the installer does not detect your CA bundle automatically, or if you are using a custom internal CA, force CA bundle mounting with the `FORCE_CA_MOUNT` environment variable: - -```bash -export FORCE_CA_MOUNT=true -export LICENSE_KEY='' -curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash - -``` - -## Adding Custom CA Certificates - -To add a custom CA certificate to the system trust store before installation: - -```bash -# Copy your CA certificate to the system trust directory -sudo cp your-ca-cert.crt /usr/local/share/ca-certificates/ - -# Update the system CA bundle -sudo update-ca-certificates -``` - -Run the installer after updating the trust store. The installer will automatically detect and mount the updated bundle. - -## TLS for Internal Services - -All internal service-to-service communication within the Kubernetes cluster uses the cluster's internal networking. Traefik handles TLS termination at the ingress layer and routes traffic to backend services. diff --git a/docs/accessanalyzer/1.0/overview/install/stepbystep.md b/docs/accessanalyzer/1.0/overview/install/stepbystep.md deleted file mode 100644 index bd418170a7..0000000000 --- a/docs/accessanalyzer/1.0/overview/install/stepbystep.md +++ /dev/null @@ -1,150 +0,0 @@ ---- -title: "Step-by-Step Installation" -description: "Detailed walkthrough of the Access Analyzer installation process" -sidebar_position: 35 ---- - -# Step-by-Step Installation - -This guide provides a detailed walkthrough of the Netwrix Access Analyzer installation process with explanations for each phase. For a condensed version, see the [Quick Install](/docs/accessanalyzer/1_0/install/quickinstall) guide. - -## Pre-Installation Checklist - -Complete the following before starting the installer: - -| Step | Action | Reference | -| --- | --- | --- | -| 1 | Provision a Linux VM meeting hardware requirements | [Hardware and System Requirements](/docs/accessanalyzer/1_0/install/requirements) | -| 2 | Configure static memory allocation on the hypervisor | [Virtualization Configuration](/docs/accessanalyzer/1_0/install/requirements#virtualization-and-hypervisor-configuration) | -| 3 | Verify outbound HTTPS connectivity to required endpoints | [Network Configuration](/docs/accessanalyzer/1_0/install/network) | -| 4 | Obtain your Netwrix license key | Contact Netwrix Sales or Support | -| 5 | Update the operating system | See step 1 below | - -## Step 1: Update the Operating System - -Ensure all system packages are current: - -```bash -sudo apt update && sudo apt upgrade -y -``` - -Reboot if kernel updates were applied: - -```bash -sudo reboot -``` - -## Step 2: Validate System Readiness (Optional) - -Run the installer in dry-run mode to verify that the system meets all requirements without making changes: - -```bash -export LICENSE_KEY='' -curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- --dry-run -``` - -Review the results in `/var/log/dspm-preflight.json`. Address any `FAIL` items before proceeding. See [Preflight Checks](/docs/accessanalyzer/1_0/install/preflight) for details on each check. - -## Step 3: Set the License Key - -Export your Netwrix license key as an environment variable: - -```bash -export LICENSE_KEY='' -``` - -:::warning -Do not store the license key in scripts or configuration files that are committed to version control. Clear your shell history after installation — see [Security Best Practices](/docs/accessanalyzer/1_0/install/security). -::: - -## Step 4: Run the Installer - -Download and execute the installer: - -```bash -curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash - -``` - -The installer executes the following phases automatically: - -### Phase 1 — Preflight Checks - -The installer validates system resources (memory, CPU, disk), kernel features (cgroups, overlay FS, namespaces), and system access. If any critical check fails, the installer exits with code `80`. If warnings are present, you are prompted to continue or abort. - -### Phase 2 — K3s Installation - -K3s (v1.33.4+k3s1) is deployed as a lightweight Kubernetes distribution. The installer configures: - -- Kubeconfig permissions (`644`) -- Secrets-at-rest encryption -- K3s service name `dspm` - -### Phase 3 — ArgoCD Installation - -ArgoCD (v3.2.0) is deployed using Kustomize-based manifests with dynamic patches. ArgoCD provides GitOps-based application lifecycle management for all Access Analyzer components. - -### Phase 4 — DSPMctl Wrapper - -The `dspmctl` command-line tool is installed to `/usr/local/bin/dspmctl`. This tool provides convenient commands for managing ArgoCD applications. See [DSPMctl CLI](/docs/accessanalyzer/1_0/install/dspmctl). - -### Phase 5 — Application Deployment - -Applications are deployed from the Netwrix OCI registry (`oci://oci.pkg.keygen.sh/netwrix/dspm-apps-helm`). ArgoCD pulls Helm charts and deploys all services into the `access-analyzer` namespace. - -### Phase 6 — Health Verification - -The installer monitors application health with a 30-minute timeout, checking every 2 seconds. Once all applications report healthy status, the installer prints a success summary. - -## Step 5: Verify the Installation - -After the installer completes successfully, verify the cluster state: - -```bash -# Check all pods across all namespaces -kubectl get pods -A - -# Check ArgoCD application sync status -kubectl get apps -n argocd - -# Check node resource usage -kubectl top nodes -``` - -All pods should be in `Running` or `Completed` status. All ArgoCD applications should show `Synced` and `Healthy`. - -## Step 6: Access the Application - -Open a browser and navigate to: - -``` -https:// -``` - -:::note -Access Analyzer uses a self-signed TLS certificate by default. Your browser will display a security warning — accept it to proceed. See [SSL / TLS Configuration](/docs/accessanalyzer/1_0/install/ssl) for custom certificate setup. -::: - -## Step 7: Create the First Admin Account - -1. On the login page, click **Create Account** -2. Enter your full name, email address, and a password -3. Click **Create Account** - -The first account created is automatically assigned the **Administrator** role with full access to all features. - -## Step 8: Sign In - -1. Enter your email address and password -2. Click **Sign In** - -You are now ready to begin configuring Access Analyzer. See [Getting Started](/docs/accessanalyzer/1_0/gettingstarted/overview) for your next steps. - -## Installation Log - -The installer writes a detailed log to `/var/log/dspm-installer.log`. If the installation fails, review this file for diagnostic information: - -```bash -cat /var/log/dspm-installer.log -``` - -For additional troubleshooting guidance, see [Troubleshooting](/docs/accessanalyzer/1_0/troubleshooting/overview). diff --git a/docs/accessanalyzer/1.0/overview/install/upgrade.md b/docs/accessanalyzer/1.0/overview/install/upgrade.md deleted file mode 100644 index 868b81dc33..0000000000 --- a/docs/accessanalyzer/1.0/overview/install/upgrade.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: "Upgrading Access Analyzer" -description: "Update Access Analyzer to a new version using DSPMctl" -sidebar_position: 70 ---- - -# Upgrading Access Analyzer - -Access Analyzer uses ArgoCD for GitOps-based application management. Upgrades are performed by updating the target revision, which triggers ArgoCD to pull and deploy the new version from the Netwrix OCI registry. - -## Upgrade Procedure - -### Step 1: Check Current Version - -```bash -dspmctl auto-status -``` - -Note the current target revision displayed for each application. - -### Step 2: Set the New Target Revision - -Update the target revision to the desired version: - -```bash -dspmctl set-revision netwrix -``` - -**Example:** - -```bash -dspmctl set-revision netwrix 1.0.7 -``` - -### Step 3: Monitor the Upgrade - -If auto-sync is enabled, ArgoCD automatically detects the revision change and begins deploying the new version. Monitor the status: - -```bash -# Watch ArgoCD application sync status -kubectl get apps -n argocd -w - -# Check DSPMctl status -dspmctl auto-status -``` - -If auto-sync is not enabled, manually trigger the sync: - -```bash -dspmctl sync netwrix.infra -dspmctl sync netwrix.core-api -``` - -### Step 4: Verify the Upgrade - -Confirm all applications are synced and healthy: - -```bash -kubectl get apps -n argocd -kubectl get pods -n access-analyzer -``` - -All applications should show `Synced` and `Healthy` status. All pods should be `Running` or `Completed`. - -## Rollback - -To revert to a previous version, set the target revision back: - -```bash -dspmctl set-revision netwrix -``` - -ArgoCD will redeploy the previous version. - -:::warning -Test upgrades in a non-production environment before applying to production systems. -::: diff --git a/docs/accessanalyzer/1.0/overview/overview.md b/docs/accessanalyzer/1.0/overview/overview.md deleted file mode 100644 index 6dc74163a7..0000000000 --- a/docs/accessanalyzer/1.0/overview/overview.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: "Intro to the Product" -description: "Introduction to Netwrix Access Analyzer and its capabilities" -sidebar_position: 10 ---- - -# Intro to the Product - -Netwrix Access Analyzer is an on-premises Data Security Posture Management (DSPM) platform that discovers, classifies, and secures sensitive data across your organization's file systems. Deployed on your own infrastructure, it provides visibility into who has access to what data, identifies overly permissive access, and detects sensitive data exposure — all without sending data to the cloud. - -## Core Capabilities - -- **Data Source Discovery** — Connect to file shares (CIFS/SMB) and other on-premises data repositories to inventory content and access permissions -- **Identity and Access Analysis** — Synchronize with Active Directory, Entra ID, and local groups to map identities, group memberships, and effective permissions -- **Sensitive Data Detection** — Scan files for PII, credentials, PHI, and financial records using built-in patterns and custom regex rules, with compliance mappings to GDPR, CCPA, HIPAA, PCI DSS, GLBA, and CMMC -- **Dashboards and Reporting** — View findings through embedded Metabase dashboards for data security posture, Active Directory insights, and sensitive data exposure -- **Audit Trail** — Maintain a full audit log of user actions and system events - -## How It Works - -1. **Configure data sources** — Add file shares and identity providers as data sources, each with an associated service account for authentication -2. **Run scans** — Create access scans to enumerate permissions and sensitive data scans to classify content -3. **Review findings** — Analyze results through dashboards, reports, and the scan execution history -4. **Take action** — Identify and remediate overly permissive access, exposed sensitive data, and policy violations - -## Deployment Model - -Access Analyzer is deployed on-premises as a self-contained Kubernetes cluster on a single Linux VM within your own network. A one-command installer provisions all required infrastructure — including K3s, ArgoCD, databases, and application services. No cloud connectivity is required. Updates are managed through ArgoCD GitOps. - -For installation instructions, see [Installation](/docs/accessanalyzer/1_0/overview/install/overview). - -## What's Next - -- [Key Concepts](/docs/accessanalyzer/1_0/overview/keyconcepts) — Learn the terminology used throughout Access Analyzer -- [Requirements](/docs/accessanalyzer/1_0/overview/requirements/overview) — Review system and connector requirements -- [Installation](/docs/accessanalyzer/1_0/overview/install/overview) — Install Access Analyzer on your infrastructure diff --git a/docs/accessanalyzer/1.0/overview/requirements/_category_.json b/docs/accessanalyzer/1.0/overview/requirements/_category_.json deleted file mode 100644 index 2047289ac1..0000000000 --- a/docs/accessanalyzer/1.0/overview/requirements/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Requirements", - "position": 30, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "overview" - } -} diff --git a/docs/accessanalyzer/1.0/overview/requirements/connectors/localgroups.md b/docs/accessanalyzer/1.0/overview/requirements/connectors/localgroups.md deleted file mode 100644 index ac5efd6ad9..0000000000 --- a/docs/accessanalyzer/1.0/overview/requirements/connectors/localgroups.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: "Local Groups" -description: "PowerShell Remoting and target machine permissions" -sidebar_position: 50 ---- - -# Local Groups - -The Local Groups connector enumerates local users and group memberships on Windows machines using PowerShell Remoting (WinRM). - -## Network Requirements - -| Port | Protocol | Direction | Description | -| --- | --- | --- | --- | -| 5985 | TCP | Access Analyzer → Target Machine | WinRM over HTTP | -| 5986 | TCP | Access Analyzer → Target Machine | WinRM over HTTPS | - -## Service Account Requirements - -| Requirement | Details | -| --- | --- | -| **Account type** | Local administrator or member of Remote Management Users group | -| **Authentication** | Username and password | -| **WinRM** | PowerShell Remoting must be enabled on target machines | - -## Enabling WinRM on Target Machines - -PowerShell Remoting must be enabled on each target machine: - -```powershell -Enable-PSRemoting -Force -``` - -For domain-joined machines, this can be configured via Group Policy: - -1. Open **Group Policy Management** -2. Navigate to **Computer Configuration** > **Administrative Templates** > **Windows Components** > **Windows Remote Management (WinRM)** > **WinRM Service** -3. Enable **Allow remote server management through WinRM** - -## Credential Type - -| Field | Value | -| --- | --- | -| **Type** | Username / Password | -| **Username format** | `MACHINE\username` or `DOMAIN\username` | - -## Connector Capabilities - -| Operation | Description | -| --- | --- | -| **Test connection** | Validates WinRM connectivity and authentication | -| **Sync** | Enumerates local users, groups, and group memberships | diff --git a/docs/accessanalyzer/1.0/overview/requirements/connectors/sharepointonline.md b/docs/accessanalyzer/1.0/overview/requirements/connectors/sharepointonline.md deleted file mode 100644 index 4e06241002..0000000000 --- a/docs/accessanalyzer/1.0/overview/requirements/connectors/sharepointonline.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: "SharePoint Online" -description: "Azure App Registration, Graph API permissions, and certificate authentication" -sidebar_position: 20 ---- - -# SharePoint Online - -The SharePoint Online connector scans SharePoint sites to enumerate content and access permissions using the Microsoft Graph API with certificate-based authentication. - -## Network Requirements - -| Port | Protocol | Direction | Description | -| --- | --- | --- | --- | -| 443 | TCP | Access Analyzer → Microsoft Graph API | HTTPS | - -## Azure App Registration - -An Azure AD (Entra ID) app registration is required for SharePoint Online connectivity. - -### Required API Permissions - -| Permission | Type | Description | -| --- | --- | --- | -| `Sites.Read.All` | Application | Read items in all site collections | - -### Registration Steps - -1. Sign in to the [Azure portal](https://portal.azure.com) and navigate to **Microsoft Entra ID** > **App registrations** -2. Click **New registration** and provide a name (for example, `Netwrix Access Analyzer - SharePoint`) -3. Under **API permissions**, add the **Microsoft Graph** application permission `Sites.Read.All` -4. Grant admin consent for the permission -5. Under **Certificates & secrets**, upload a certificate (`.cer` or `.pem` public key) -6. Note the **Application (client) ID** and **Tenant ID** - -## Credential Type - -| Field | Value | -| --- | --- | -| **Type** | Certificate | -| **Client ID** | Application (client) ID from the app registration | -| **Tenant ID** | Directory (tenant) ID | -| **Certificate** | Private key file (`.pem`) corresponding to the uploaded public key | - -## Connector Capabilities - -| Operation | Description | -| --- | --- | -| **Test connection** | Validates Graph API connectivity and certificate authentication | -| **Access scan** | Enumerates SharePoint sites, document libraries, files, and permissions | -| **Get object** | Retrieves specific site or document metadata | - -## Scan Configuration Options - -| Option | Description | -| --- | --- | -| **Site filtering** | Include or exclude specific SharePoint sites | diff --git a/docs/accessanalyzer/1.0/overview/requirements/database/_category_.json b/docs/accessanalyzer/1.0/overview/requirements/database/_category_.json deleted file mode 100644 index 32e43edc04..0000000000 --- a/docs/accessanalyzer/1.0/overview/requirements/database/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "Database Requirements", - "position": 20, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "postgresql" - } -} diff --git a/docs/accessanalyzer/1.0/overview/requirements/database/clickhouse.md b/docs/accessanalyzer/1.0/overview/requirements/database/clickhouse.md deleted file mode 100644 index 868c10e9da..0000000000 --- a/docs/accessanalyzer/1.0/overview/requirements/database/clickhouse.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: "ClickHouse" -description: "ClickHouse version and configuration" -sidebar_position: 20 ---- - -# ClickHouse - -ClickHouse is a columnar analytics database used by Access Analyzer for scan results, reporting data, and observability (OpenTelemetry traces and logs). - -## Version - -| Component | Value | -| --- | --- | -| **ClickHouse version** | 25.8.13 | -| **Namespace** | `access-analyzer` | -| **HTTP interface port** | 8123 | -| **Native protocol port** | 9000 | - -## Provisioning - -ClickHouse is **automatically provisioned** by the installer. No manual setup is required. - -Database passwords are auto-generated and stored as Kubernetes secrets. - -## Data Stored - -- Scan results and analytics data -- OpenTelemetry traces and logs (via the `access_analyzer_logs` database) -- Reporting and dashboard data queried by Metabase diff --git a/docs/accessanalyzer/1.0/overview/requirements/database/postgresql.md b/docs/accessanalyzer/1.0/overview/requirements/database/postgresql.md deleted file mode 100644 index 4e5f9dba79..0000000000 --- a/docs/accessanalyzer/1.0/overview/requirements/database/postgresql.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: "PostgreSQL" -description: "PostgreSQL version and configuration" -sidebar_position: 10 ---- - -# PostgreSQL - -PostgreSQL serves as the primary relational database for Access Analyzer, storing configuration, user accounts, scan metadata, connector state, and application data. - -## Version - -| Component | Value | -| --- | --- | -| **PostgreSQL version** | 14.18 | -| **Namespace** | `access-analyzer` | - -## Provisioning - -PostgreSQL is **automatically provisioned** by the installer. No manual database setup, schema creation, or user configuration is required. - -The installer creates the following database users during deployment: - -| User | Purpose | -| --- | --- | -| `postgres` | Superuser for administrative tasks | -| `connector_readonly` | Read-only access for connector queries | -| `connector_execution_update` | Write access for connector execution state | -| `connector_state_readwrite` | Read/write access for connector state management | - -All database passwords are auto-generated by the `dspm-utility` secret initialization process and stored as Kubernetes secrets. - -## Data Stored - -- User accounts and authentication -- Source and scan configuration -- Service accounts (encrypted credentials) -- Connector state and execution metadata -- Application settings and feature flags -- Audit log entries diff --git a/docs/accessanalyzer/1.0/overview/requirements/database/redis.md b/docs/accessanalyzer/1.0/overview/requirements/database/redis.md deleted file mode 100644 index 9cc26151cb..0000000000 --- a/docs/accessanalyzer/1.0/overview/requirements/database/redis.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: "Redis" -description: "Redis version and configuration" -sidebar_position: 30 ---- - -# Redis - -Redis provides in-memory caching, session storage, and job queue management for Access Analyzer. - -## Version - -| Component | Value | -| --- | --- | -| **Redis version** | 8.4.0 | -| **Namespace** | `access-analyzer` | -| **Port** | 6379 | - -## Provisioning - -Redis is **automatically provisioned** by the installer. No manual setup is required. - -## Data Stored - -| Function | Description | -| --- | --- | -| **User sessions** | Session data for authenticated users (with IP validation and configurable TTL) | -| **Sidekiq job queues** | Background job processing for scans, syncs, mailers, and system tasks | -| **Application cache** | Frequently accessed data for reduced database load | - -## Job Queues - -Redis backs the Sidekiq job processing system, which uses the following queues: - -| Queue | Purpose | -| --- | --- | -| `critical` | High-priority system operations | -| `scans` | Scan execution jobs | -| `syncs` | Identity synchronization jobs | -| `scheduler` | Scheduled job dispatch | -| `default` | General-purpose jobs | -| `mailers` | Email notification delivery | -| `low` | Low-priority background tasks | diff --git a/docs/accessanalyzer/1.0/overview/requirements/overview.md b/docs/accessanalyzer/1.0/overview/requirements/overview.md deleted file mode 100644 index 84fa865f34..0000000000 --- a/docs/accessanalyzer/1.0/overview/requirements/overview.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: "Requirements" -description: "System, database, and connector requirements for Access Analyzer" -sidebar_position: 1 ---- - -# Requirements - -This section covers all prerequisites for deploying and operating Netwrix Access Analyzer. - -## System Requirements - -The Access Analyzer VM must meet minimum hardware, operating system, and kernel requirements. The installer validates these automatically during [preflight checks](/docs/accessanalyzer/1_0/install/preflight). - -- [Kubernetes and Operating System](/docs/accessanalyzer/1_0/requirements/system/kubernetes) — OS version, kernel, and K3s details -- [Hardware and Resource Allocation](/docs/accessanalyzer/1_0/requirements/system/hardware) — CPU, memory, disk, and virtualization -- [Network and Port Requirements](/docs/accessanalyzer/1_0/requirements/system/network) — Outbound endpoints, internal ports, and firewall rules - -## Database Requirements - -All databases are automatically provisioned by the installer. No manual database setup is required. - -- [PostgreSQL](/docs/accessanalyzer/1_0/requirements/database/postgresql) — Primary relational database -- [ClickHouse](/docs/accessanalyzer/1_0/requirements/database/clickhouse) — Analytics and observability database -- [Redis](/docs/accessanalyzer/1_0/requirements/database/redis) — Session cache and job queues - -## Connector Requirements - -Each connector type has specific requirements for authentication, network access, and permissions on the target system. - -- [CIFS / SMB File Share](/docs/accessanalyzer/1_0/requirements/connectors/cifs) — SMB file share scanning -- [SharePoint Online](/docs/accessanalyzer/1_0/requirements/connectors/sharepointonline) — SharePoint site scanning -- [Active Directory](/docs/accessanalyzer/1_0/requirements/connectors/activedirectory) — AD identity synchronization -- [Entra ID](/docs/accessanalyzer/1_0/requirements/connectors/entraid) — Entra ID connection testing -- [Local Groups](/docs/accessanalyzer/1_0/requirements/connectors/localgroups) — Local group enumeration diff --git a/docs/accessanalyzer/1.0/overview/requirements/system/hardware.md b/docs/accessanalyzer/1.0/overview/requirements/system/hardware.md deleted file mode 100644 index 7787c810de..0000000000 --- a/docs/accessanalyzer/1.0/overview/requirements/system/hardware.md +++ /dev/null @@ -1,84 +0,0 @@ ---- -title: "Hardware and Resource Allocation" -description: "CPU, memory, storage, and virtualization requirements" -sidebar_position: 20 ---- - -# Hardware and Resource Allocation - -Access Analyzer is deployed on a single Linux virtual machine. This page details the hardware requirements and virtualization configuration. - -## Deployment Sizing - -| Size | CPU | Memory | Disk | Use Case | -| --- | --- | --- | --- | --- | -| **Small** | 2 vCPUs (4 recommended) | 8 GB (16 GB recommended) | 20 GB free (50 GB recommended) | Evaluation and small environments | -| **Medium** | 8 vCPUs | 32 GB | 100 GB SSD | Mid-size environments | -| **Large** | 16 vCPUs | 64 GB | 500 GB SSD | Large enterprise environments | - -All sizes require SSD or NVMe storage for optimal database performance. - -## Disk Space by Directory - -| Path | Minimum Free Space | Purpose | -| --- | --- | --- | -| `/` | 20 GB | Root filesystem | -| `/var` | 20 GB | K3s data, containers, logs | -| `/var/lib` | 20 GB | K3s data directory | -| `/var/log` | 5 GB | System and application logs | -| `/etc` | 1 GB | Configuration files | - -## Virtualization Requirements - -When running on a hypervisor, the following must be supported: - -| Requirement | Details | -| --- | --- | -| **Linux namespaces** | NET, PID, IPC, UTS, MNT, USER | -| **Control groups** | cgroups v1 or v2 with memory and CPU controllers | -| **Overlay filesystem** | Kernel module for container layers | -| **iptables** | Kubernetes networking | - -## Hypervisor Configuration - -Configure **static memory allocation** for the Access Analyzer VM. Dynamic or ballooned memory can cause resource underestimation and out-of-memory conditions. - -### VMware vSphere / ESXi - -Disable memory ballooning: - -``` -sched.mem.pshare.enable = "FALSE" -mem.balloon.enable = "FALSE" -``` - -Set these in **VM Settings** > **VM Options** > **Advanced** > **Edit Configuration**. - -### Microsoft Hyper-V - -Use static memory: - -```powershell -Set-VMMemory -VMName "" -DynamicMemoryEnabled $false -StartupBytes 16GB -``` - -### KVM / QEMU - -Use hugepages: - -```xml - - - -``` - -## Swap - -| System Memory | Recommendation | -| --- | --- | -| 16 GB or more | Swap is optional | -| Less than 16 GB | 2–4 GB swap recommended to prevent OOM during container pulls | - -## Resource Scaling - -The installer supports a `--size` flag (1–10) that scales memory thresholds by the specified multiplier. For example, `--size 2` doubles the minimum and recommended memory requirements. See [Environment Variables](/docs/accessanalyzer/1_0/install/environmentvariables). diff --git a/docs/accessanalyzer/1.0/reports-overview/_category_.json b/docs/accessanalyzer/1.0/reports-overview/_category_.json new file mode 100644 index 0000000000..6385d557da --- /dev/null +++ b/docs/accessanalyzer/1.0/reports-overview/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Reports Overview", + "position": 60, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/reports-overview/access.md b/docs/accessanalyzer/1.0/reports-overview/access.md new file mode 100644 index 0000000000..9a04e9e2bb --- /dev/null +++ b/docs/accessanalyzer/1.0/reports-overview/access.md @@ -0,0 +1,9 @@ +--- +title: "Access" +description: "Access reports overview" +sidebar_position: 20 +--- + +# Access + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/reports-overview/activity.md b/docs/accessanalyzer/1.0/reports-overview/activity.md new file mode 100644 index 0000000000..81f8f5a9ca --- /dev/null +++ b/docs/accessanalyzer/1.0/reports-overview/activity.md @@ -0,0 +1,9 @@ +--- +title: "Activity" +description: "Activity reports overview" +sidebar_position: 40 +--- + +# Activity + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/reports-overview/content.md b/docs/accessanalyzer/1.0/reports-overview/content.md new file mode 100644 index 0000000000..855c66175a --- /dev/null +++ b/docs/accessanalyzer/1.0/reports-overview/content.md @@ -0,0 +1,9 @@ +--- +title: "Content" +description: "Content reports overview" +sidebar_position: 30 +--- + +# Content + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/reports-overview/how-to-analyze-the-data.md b/docs/accessanalyzer/1.0/reports-overview/how-to-analyze-the-data.md new file mode 100644 index 0000000000..704180131f --- /dev/null +++ b/docs/accessanalyzer/1.0/reports-overview/how-to-analyze-the-data.md @@ -0,0 +1,9 @@ +--- +title: "How to Analyze the Data" +description: "Learn how to analyze data presented in reports" +sidebar_position: 10 +--- + +# How to Analyze the Data + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/reports-overview/my-reports.md b/docs/accessanalyzer/1.0/reports-overview/my-reports.md new file mode 100644 index 0000000000..26f3a69cab --- /dev/null +++ b/docs/accessanalyzer/1.0/reports-overview/my-reports.md @@ -0,0 +1,9 @@ +--- +title: "My Reports" +description: "Custom saved reports" +sidebar_position: 60 +--- + +# My Reports + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/reports-overview/sensitive-data.md b/docs/accessanalyzer/1.0/reports-overview/sensitive-data.md new file mode 100644 index 0000000000..6cdd68075f --- /dev/null +++ b/docs/accessanalyzer/1.0/reports-overview/sensitive-data.md @@ -0,0 +1,9 @@ +--- +title: "Sensitive Data" +description: "Sensitive data reports overview" +sidebar_position: 50 +--- + +# Sensitive Data + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/scanners/_category_.json b/docs/accessanalyzer/1.0/scanners/_category_.json new file mode 100644 index 0000000000..06591067c1 --- /dev/null +++ b/docs/accessanalyzer/1.0/scanners/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Utilizing Scanners", + "position": 40, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/scanners/overview.md b/docs/accessanalyzer/1.0/scanners/overview.md new file mode 100644 index 0000000000..d540453a0f --- /dev/null +++ b/docs/accessanalyzer/1.0/scanners/overview.md @@ -0,0 +1,9 @@ +--- +title: "Utilizing Scanners" +description: "Overview of scanner capabilities in Access Analyzer" +sidebar_position: 10 +--- + +# Utilizing Scanners + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/overview/requirements/system/_category_.json b/docs/accessanalyzer/1.0/system/_category_.json similarity index 88% rename from docs/accessanalyzer/1.0/overview/requirements/system/_category_.json rename to docs/accessanalyzer/1.0/system/_category_.json index 950fb05a5f..684c03e579 100644 --- a/docs/accessanalyzer/1.0/overview/requirements/system/_category_.json +++ b/docs/accessanalyzer/1.0/system/_category_.json @@ -1,6 +1,6 @@ { "label": "System Requirements", - "position": 10, + "position": 12, "collapsed": true, "collapsible": true, "link": { diff --git a/docs/accessanalyzer/1.0/overview/requirements/system/kubernetes.md b/docs/accessanalyzer/1.0/system/kubernetes.md similarity index 100% rename from docs/accessanalyzer/1.0/overview/requirements/system/kubernetes.md rename to docs/accessanalyzer/1.0/system/kubernetes.md diff --git a/docs/accessanalyzer/1.0/overview/requirements/system/network.md b/docs/accessanalyzer/1.0/system/network.md similarity index 100% rename from docs/accessanalyzer/1.0/overview/requirements/system/network.md rename to docs/accessanalyzer/1.0/system/network.md diff --git a/docs/accessanalyzer/1.0/overview/install/requirements.md b/docs/accessanalyzer/1.0/system/requirements.md similarity index 100% rename from docs/accessanalyzer/1.0/overview/install/requirements.md rename to docs/accessanalyzer/1.0/system/requirements.md From c98573fd7b361123a12b5f6e2e8f3986023aa1ed Mon Sep 17 00:00:00 2001 From: carlos-mejia_nwx Date: Tue, 31 Mar 2026 11:36:28 -0400 Subject: [PATCH 16/62] =?UTF-8?q?AA26:=20Restructure=20outline=20=E2=80=94?= =?UTF-8?q?=20File=20Servers=20subsections,=20merge=20Dashboards/Reports,?= =?UTF-8?q?=20scanner=20subsections?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - File Servers: converted to directory, moved CIFS under it, added Unity, Celerra, VNX, NetApp - Dashboards and Reports: merged Dashboards Overview + Reports Overview into single section - Removed access, content, activity, sensitive data report pages; kept My Reports - Added How to Analyze Reports subsection - Utilizing Scanners: renamed overview, added Best Practices subsection Co-Authored-By: Claude Opus 4.6 --- docs/accessanalyzer/1.0/connectors/_category_.json | 6 +----- docs/accessanalyzer/1.0/connectors/file-servers.md | 9 --------- .../1.0/connectors/file-servers/_category_.json | 6 ++++++ .../1.0/connectors/file-servers/celerra.md | 9 +++++++++ .../1.0/connectors/{ => file-servers}/cifs.md | 0 .../accessanalyzer/1.0/connectors/file-servers/netapp.md | 9 +++++++++ docs/accessanalyzer/1.0/connectors/file-servers/unity.md | 9 +++++++++ docs/accessanalyzer/1.0/connectors/file-servers/vnx.md | 9 +++++++++ .../1.0/dashboards-overview/how-to-analyze-the-data.md | 9 --------- .../_category_.json | 2 +- .../active-directory-dashboard/_category_.json | 2 +- .../active-directory-dashboard/overview.md | 9 +++++++++ .../data-security-dashboard/_category_.json | 2 +- .../data-security-dashboard/activity.md | 0 .../data-security-dashboard/overview.md | 0 .../1.0/dashboards-reports/how-to-analyze-reports.md | 9 +++++++++ .../how-to-analyze-the-data.md | 2 +- .../my-reports.md | 2 +- docs/accessanalyzer/1.0/reports-overview/_category_.json | 6 ------ docs/accessanalyzer/1.0/reports-overview/access.md | 9 --------- docs/accessanalyzer/1.0/reports-overview/activity.md | 9 --------- docs/accessanalyzer/1.0/reports-overview/content.md | 9 --------- .../1.0/reports-overview/sensitive-data.md | 9 --------- docs/accessanalyzer/1.0/scanners/best-practices.md | 9 +++++++++ docs/accessanalyzer/1.0/scanners/overview.md | 4 ++-- 25 files changed, 77 insertions(+), 72 deletions(-) delete mode 100644 docs/accessanalyzer/1.0/connectors/file-servers.md create mode 100644 docs/accessanalyzer/1.0/connectors/file-servers/_category_.json create mode 100644 docs/accessanalyzer/1.0/connectors/file-servers/celerra.md rename docs/accessanalyzer/1.0/connectors/{ => file-servers}/cifs.md (100%) create mode 100644 docs/accessanalyzer/1.0/connectors/file-servers/netapp.md create mode 100644 docs/accessanalyzer/1.0/connectors/file-servers/unity.md create mode 100644 docs/accessanalyzer/1.0/connectors/file-servers/vnx.md delete mode 100644 docs/accessanalyzer/1.0/dashboards-overview/how-to-analyze-the-data.md rename docs/accessanalyzer/1.0/{dashboards-overview => dashboards-reports}/_category_.json (63%) rename docs/accessanalyzer/1.0/{dashboards-overview => dashboards-reports}/active-directory-dashboard/_category_.json (83%) create mode 100644 docs/accessanalyzer/1.0/dashboards-reports/active-directory-dashboard/overview.md rename docs/accessanalyzer/1.0/{dashboards-overview => dashboards-reports}/data-security-dashboard/_category_.json (82%) rename docs/accessanalyzer/1.0/{dashboards-overview => dashboards-reports}/data-security-dashboard/activity.md (100%) rename docs/accessanalyzer/1.0/{dashboards-overview => dashboards-reports}/data-security-dashboard/overview.md (100%) create mode 100644 docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-reports.md rename docs/accessanalyzer/1.0/{reports-overview => dashboards-reports}/how-to-analyze-the-data.md (60%) rename docs/accessanalyzer/1.0/{reports-overview => dashboards-reports}/my-reports.md (82%) delete mode 100644 docs/accessanalyzer/1.0/reports-overview/_category_.json delete mode 100644 docs/accessanalyzer/1.0/reports-overview/access.md delete mode 100644 docs/accessanalyzer/1.0/reports-overview/activity.md delete mode 100644 docs/accessanalyzer/1.0/reports-overview/content.md delete mode 100644 docs/accessanalyzer/1.0/reports-overview/sensitive-data.md create mode 100644 docs/accessanalyzer/1.0/scanners/best-practices.md diff --git a/docs/accessanalyzer/1.0/connectors/_category_.json b/docs/accessanalyzer/1.0/connectors/_category_.json index 4ebd7ecb5d..67fabb3b53 100644 --- a/docs/accessanalyzer/1.0/connectors/_category_.json +++ b/docs/accessanalyzer/1.0/connectors/_category_.json @@ -2,9 +2,5 @@ "label": "Connector Requirements", "position": 14, "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "cifs" - } + "collapsible": true } diff --git a/docs/accessanalyzer/1.0/connectors/file-servers.md b/docs/accessanalyzer/1.0/connectors/file-servers.md deleted file mode 100644 index a70313521e..0000000000 --- a/docs/accessanalyzer/1.0/connectors/file-servers.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "File Servers" -description: "File server connector requirements for Access Analyzer" -sidebar_position: 20 ---- - -# File Servers - -*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/connectors/file-servers/_category_.json b/docs/accessanalyzer/1.0/connectors/file-servers/_category_.json new file mode 100644 index 0000000000..5923518b84 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/file-servers/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "File Servers", + "position": 20, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/connectors/file-servers/celerra.md b/docs/accessanalyzer/1.0/connectors/file-servers/celerra.md new file mode 100644 index 0000000000..e562473a05 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/file-servers/celerra.md @@ -0,0 +1,9 @@ +--- +title: "Celerra" +description: "Connector requirements for Dell Celerra file servers" +sidebar_position: 30 +--- + +# Celerra + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/connectors/cifs.md b/docs/accessanalyzer/1.0/connectors/file-servers/cifs.md similarity index 100% rename from docs/accessanalyzer/1.0/connectors/cifs.md rename to docs/accessanalyzer/1.0/connectors/file-servers/cifs.md diff --git a/docs/accessanalyzer/1.0/connectors/file-servers/netapp.md b/docs/accessanalyzer/1.0/connectors/file-servers/netapp.md new file mode 100644 index 0000000000..17eab35605 --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/file-servers/netapp.md @@ -0,0 +1,9 @@ +--- +title: "NetApp" +description: "Connector requirements for NetApp file servers" +sidebar_position: 50 +--- + +# NetApp + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/connectors/file-servers/unity.md b/docs/accessanalyzer/1.0/connectors/file-servers/unity.md new file mode 100644 index 0000000000..55cc8ba73a --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/file-servers/unity.md @@ -0,0 +1,9 @@ +--- +title: "Unity" +description: "Connector requirements for Dell Unity file servers" +sidebar_position: 20 +--- + +# Unity + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/connectors/file-servers/vnx.md b/docs/accessanalyzer/1.0/connectors/file-servers/vnx.md new file mode 100644 index 0000000000..cbaba1af7a --- /dev/null +++ b/docs/accessanalyzer/1.0/connectors/file-servers/vnx.md @@ -0,0 +1,9 @@ +--- +title: "VNX" +description: "Connector requirements for Dell VNX file servers" +sidebar_position: 40 +--- + +# VNX + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/dashboards-overview/how-to-analyze-the-data.md b/docs/accessanalyzer/1.0/dashboards-overview/how-to-analyze-the-data.md deleted file mode 100644 index dfb66b947e..0000000000 --- a/docs/accessanalyzer/1.0/dashboards-overview/how-to-analyze-the-data.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "How to Analyze the Data" -description: "Learn how to analyze data presented in dashboards" -sidebar_position: 10 ---- - -# How to Analyze the Data - -*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/dashboards-overview/_category_.json b/docs/accessanalyzer/1.0/dashboards-reports/_category_.json similarity index 63% rename from docs/accessanalyzer/1.0/dashboards-overview/_category_.json rename to docs/accessanalyzer/1.0/dashboards-reports/_category_.json index 2ce5a39907..91e8e50995 100644 --- a/docs/accessanalyzer/1.0/dashboards-overview/_category_.json +++ b/docs/accessanalyzer/1.0/dashboards-reports/_category_.json @@ -1,5 +1,5 @@ { - "label": "Dashboards Overview", + "label": "Dashboards and Reports", "position": 50, "collapsed": true, "collapsible": true diff --git a/docs/accessanalyzer/1.0/dashboards-overview/active-directory-dashboard/_category_.json b/docs/accessanalyzer/1.0/dashboards-reports/active-directory-dashboard/_category_.json similarity index 83% rename from docs/accessanalyzer/1.0/dashboards-overview/active-directory-dashboard/_category_.json rename to docs/accessanalyzer/1.0/dashboards-reports/active-directory-dashboard/_category_.json index 527eda587f..1625f523d8 100644 --- a/docs/accessanalyzer/1.0/dashboards-overview/active-directory-dashboard/_category_.json +++ b/docs/accessanalyzer/1.0/dashboards-reports/active-directory-dashboard/_category_.json @@ -1,6 +1,6 @@ { "label": "Active Directory Dashboard", - "position": 30, + "position": 50, "collapsed": true, "collapsible": true } diff --git a/docs/accessanalyzer/1.0/dashboards-reports/active-directory-dashboard/overview.md b/docs/accessanalyzer/1.0/dashboards-reports/active-directory-dashboard/overview.md new file mode 100644 index 0000000000..be8af55027 --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards-reports/active-directory-dashboard/overview.md @@ -0,0 +1,9 @@ +--- +title: "Overview" +description: "Overview of the Active Directory Dashboard" +sidebar_position: 10 +--- + +# Overview + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/_category_.json b/docs/accessanalyzer/1.0/dashboards-reports/data-security-dashboard/_category_.json similarity index 82% rename from docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/_category_.json rename to docs/accessanalyzer/1.0/dashboards-reports/data-security-dashboard/_category_.json index d27cd7ee77..48567d27b0 100644 --- a/docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/_category_.json +++ b/docs/accessanalyzer/1.0/dashboards-reports/data-security-dashboard/_category_.json @@ -1,6 +1,6 @@ { "label": "Data Security Dashboard", - "position": 20, + "position": 40, "collapsed": true, "collapsible": true } diff --git a/docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/activity.md b/docs/accessanalyzer/1.0/dashboards-reports/data-security-dashboard/activity.md similarity index 100% rename from docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/activity.md rename to docs/accessanalyzer/1.0/dashboards-reports/data-security-dashboard/activity.md diff --git a/docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/overview.md b/docs/accessanalyzer/1.0/dashboards-reports/data-security-dashboard/overview.md similarity index 100% rename from docs/accessanalyzer/1.0/dashboards-overview/data-security-dashboard/overview.md rename to docs/accessanalyzer/1.0/dashboards-reports/data-security-dashboard/overview.md diff --git a/docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-reports.md b/docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-reports.md new file mode 100644 index 0000000000..3070386614 --- /dev/null +++ b/docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-reports.md @@ -0,0 +1,9 @@ +--- +title: "How to Analyze Reports" +description: "Guide to analyzing reports in Access Analyzer" +sidebar_position: 20 +--- + +# How to Analyze Reports + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/reports-overview/how-to-analyze-the-data.md b/docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-the-data.md similarity index 60% rename from docs/accessanalyzer/1.0/reports-overview/how-to-analyze-the-data.md rename to docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-the-data.md index 704180131f..c6dbb29a93 100644 --- a/docs/accessanalyzer/1.0/reports-overview/how-to-analyze-the-data.md +++ b/docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-the-data.md @@ -1,6 +1,6 @@ --- title: "How to Analyze the Data" -description: "Learn how to analyze data presented in reports" +description: "Guide to analyzing data using dashboards in Access Analyzer" sidebar_position: 10 --- diff --git a/docs/accessanalyzer/1.0/reports-overview/my-reports.md b/docs/accessanalyzer/1.0/dashboards-reports/my-reports.md similarity index 82% rename from docs/accessanalyzer/1.0/reports-overview/my-reports.md rename to docs/accessanalyzer/1.0/dashboards-reports/my-reports.md index 26f3a69cab..5b232cd88a 100644 --- a/docs/accessanalyzer/1.0/reports-overview/my-reports.md +++ b/docs/accessanalyzer/1.0/dashboards-reports/my-reports.md @@ -1,7 +1,7 @@ --- title: "My Reports" description: "Custom saved reports" -sidebar_position: 60 +sidebar_position: 30 --- # My Reports diff --git a/docs/accessanalyzer/1.0/reports-overview/_category_.json b/docs/accessanalyzer/1.0/reports-overview/_category_.json deleted file mode 100644 index 6385d557da..0000000000 --- a/docs/accessanalyzer/1.0/reports-overview/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Reports Overview", - "position": 60, - "collapsed": true, - "collapsible": true -} diff --git a/docs/accessanalyzer/1.0/reports-overview/access.md b/docs/accessanalyzer/1.0/reports-overview/access.md deleted file mode 100644 index 9a04e9e2bb..0000000000 --- a/docs/accessanalyzer/1.0/reports-overview/access.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Access" -description: "Access reports overview" -sidebar_position: 20 ---- - -# Access - -*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/reports-overview/activity.md b/docs/accessanalyzer/1.0/reports-overview/activity.md deleted file mode 100644 index 81f8f5a9ca..0000000000 --- a/docs/accessanalyzer/1.0/reports-overview/activity.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Activity" -description: "Activity reports overview" -sidebar_position: 40 ---- - -# Activity - -*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/reports-overview/content.md b/docs/accessanalyzer/1.0/reports-overview/content.md deleted file mode 100644 index 855c66175a..0000000000 --- a/docs/accessanalyzer/1.0/reports-overview/content.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Content" -description: "Content reports overview" -sidebar_position: 30 ---- - -# Content - -*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/reports-overview/sensitive-data.md b/docs/accessanalyzer/1.0/reports-overview/sensitive-data.md deleted file mode 100644 index 6cdd68075f..0000000000 --- a/docs/accessanalyzer/1.0/reports-overview/sensitive-data.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Sensitive Data" -description: "Sensitive data reports overview" -sidebar_position: 50 ---- - -# Sensitive Data - -*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/scanners/best-practices.md b/docs/accessanalyzer/1.0/scanners/best-practices.md new file mode 100644 index 0000000000..01fabacf57 --- /dev/null +++ b/docs/accessanalyzer/1.0/scanners/best-practices.md @@ -0,0 +1,9 @@ +--- +title: "Best Practices" +description: "Best practices for configuring and running scanners in Access Analyzer" +sidebar_position: 20 +--- + +# Best Practices + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/scanners/overview.md b/docs/accessanalyzer/1.0/scanners/overview.md index d540453a0f..2c3087426a 100644 --- a/docs/accessanalyzer/1.0/scanners/overview.md +++ b/docs/accessanalyzer/1.0/scanners/overview.md @@ -1,9 +1,9 @@ --- -title: "Utilizing Scanners" +title: "Overview of Scanners" description: "Overview of scanner capabilities in Access Analyzer" sidebar_position: 10 --- -# Utilizing Scanners +# Overview of Scanners *Content coming soon.* From 2f98a3677d36ded7924bb972a7ff53029901533b Mon Sep 17 00:00:00 2001 From: carlos-mejia_nwx Date: Mon, 6 Apr 2026 17:44:44 -0400 Subject: [PATCH 17/62] AA26: Structural restructure and naming improvements across documentation outline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Move System Requirements under Installation - Rename 'Start Collecting Data' → 'Quick Start Guides'; rename 4 scan guide pages to 'Scanning X' pattern - Convert scan guide pages to directories; nest source group wizard pages under each module - Rename 'Configurations and Making Changes' → 'Configuration'; 'Configuration Node' → 'Settings' - Reorder Settings pages to match UI sidebar (Service Accounts → Source Groups → Scans → Scan Executions → Sensitive Data → Users → Application Settings → System Logs → Notifications) - Remove Sources page (replaced by Source Groups) - Add Notifications stub page - Convert Sensitive Data to directory; move MIP Labeling as child page - Move Activity Monitor Integration under Quick Start Guides; rename to 'Activity Monitor Integration' - Rename 'Utilizing Scanners' → 'Scanners' - Fix duplicate connector titles (Entra ID and SharePoint Online both had 'Setting Up Requirements Within Entra') - Rename connector pages: Client Secret Configuration, Certificate Configuration, Entra Tenant Requirements, App Permissions in Entra - Populate connector prerequisite pages (AD, File Servers, Entra ID, SharePoint Online) with real content - Add Scanners overview page (Kubernetes-based architecture) - Naming/grammar: remove 'My First', 'Utilizing', 'Understanding the', 'How to', 'Setting up' prefixes across titles Co-Authored-By: Claude Sonnet 4.6 --- .../_category_.json | 6 -- .../1.0/configurations/_category_.json | 2 +- .../configuration-node/_category_.json | 2 +- .../application-settings.md | 2 +- .../configurations/configuration-node/logs.md | 8 +-- .../configuration-node/notifications.md | 9 +++ .../sensitive-data/_category_.json | 6 ++ .../sensitive-data/mip-labeling.md} | 6 +- .../overview.md} | 2 +- .../configuration-node/service-accounts.md | 2 +- .../configuration-node/source-groups.md | 2 +- .../configuration-node/sources.md | 9 --- .../configuration-node/users.md | 2 +- .../source-group-changes/_category_.json | 6 -- .../1.0/connectors/activedirectory.md | 48 ++++++-------- .../entra-id/app-registration-secret.md | 55 ++++++++++++++-- .../connectors/entra-id/entra-requirements.md | 66 ++++++++++++++++++- .../1.0/connectors/entra-id/overview.md | 4 +- .../1.0/connectors/file-servers/cifs.md | 63 +++++++++--------- .../sharepoint-online/azure-permissions.md | 65 ++++++++++++++++-- .../tenant-certificate-config.md | 58 ++++++++++++++-- .../how-to-analyze-reports.md | 9 --- .../how-to-analyze-the-data.md | 6 +- .../1.0/gettingstarted/_category_.json | 2 +- .../gettingstarted/active-directory-sync.md | 9 --- .../active-directory-sync/_category_.json | 6 ++ .../active-directory.md | 0 .../activity-data/_category_.json | 2 +- .../_category_.json | 6 ++ .../activity-monitor-integration/overview.md | 4 +- .../1.0/gettingstarted/entra-id-sync.md | 9 --- .../entra-id-sync/_category_.json | 6 ++ .../entra-id-sync}/entra-id.md | 0 .../1.0/gettingstarted/file-server-scans.md | 9 --- .../file-server-scans/_category_.json | 6 ++ .../file-server-scans}/file-server.md | 0 .../gettingstarted/first-service-account.md | 6 +- .../gettingstarted/sharepoint-online-scan.md | 9 --- .../sharepoint-online-scan/_category_.json | 6 ++ .../sharepoint-online.md | 0 .../1.0/gettingstarted/source-group-wizard.md | 6 +- .../1.0/install/_category_.json | 2 +- .../1.0/install/system/_category_.json | 6 ++ .../1.0/{ => install}/system/kubernetes.md | 0 .../1.0/{ => install}/system/network.md | 0 .../1.0/{ => install}/system/requirements.md | 0 .../1.0/scanners/_category_.json | 2 +- .../1.0/scanners/best-practices.md | 4 +- docs/accessanalyzer/1.0/scanners/overview.md | 27 +++++++- .../accessanalyzer/1.0/system/_category_.json | 10 --- 50 files changed, 392 insertions(+), 183 deletions(-) delete mode 100644 docs/accessanalyzer/1.0/activity-monitor-integration/_category_.json create mode 100644 docs/accessanalyzer/1.0/configurations/configuration-node/notifications.md create mode 100644 docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data/_category_.json rename docs/accessanalyzer/1.0/configurations/{mip-labeling-workflow.md => configuration-node/sensitive-data/mip-labeling.md} (58%) rename docs/accessanalyzer/1.0/configurations/configuration-node/{sensitive-data.md => sensitive-data/overview.md} (87%) delete mode 100644 docs/accessanalyzer/1.0/configurations/configuration-node/sources.md delete mode 100644 docs/accessanalyzer/1.0/configurations/source-group-changes/_category_.json delete mode 100644 docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-reports.md delete mode 100644 docs/accessanalyzer/1.0/gettingstarted/active-directory-sync.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/active-directory-sync/_category_.json rename docs/accessanalyzer/1.0/{configurations/source-group-changes => gettingstarted/active-directory-sync}/active-directory.md (100%) create mode 100644 docs/accessanalyzer/1.0/gettingstarted/activity-monitor-integration/_category_.json rename docs/accessanalyzer/1.0/{ => gettingstarted}/activity-monitor-integration/overview.md (58%) delete mode 100644 docs/accessanalyzer/1.0/gettingstarted/entra-id-sync.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/entra-id-sync/_category_.json rename docs/accessanalyzer/1.0/{configurations/source-group-changes => gettingstarted/entra-id-sync}/entra-id.md (100%) delete mode 100644 docs/accessanalyzer/1.0/gettingstarted/file-server-scans.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/file-server-scans/_category_.json rename docs/accessanalyzer/1.0/{configurations/source-group-changes => gettingstarted/file-server-scans}/file-server.md (100%) delete mode 100644 docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan.md create mode 100644 docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan/_category_.json rename docs/accessanalyzer/1.0/{configurations/source-group-changes => gettingstarted/sharepoint-online-scan}/sharepoint-online.md (100%) create mode 100644 docs/accessanalyzer/1.0/install/system/_category_.json rename docs/accessanalyzer/1.0/{ => install}/system/kubernetes.md (100%) rename docs/accessanalyzer/1.0/{ => install}/system/network.md (100%) rename docs/accessanalyzer/1.0/{ => install}/system/requirements.md (100%) delete mode 100644 docs/accessanalyzer/1.0/system/_category_.json diff --git a/docs/accessanalyzer/1.0/activity-monitor-integration/_category_.json b/docs/accessanalyzer/1.0/activity-monitor-integration/_category_.json deleted file mode 100644 index 463f554a78..0000000000 --- a/docs/accessanalyzer/1.0/activity-monitor-integration/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Setting up Activity Monitor Integration", - "position": 70, - "collapsed": true, - "collapsible": true -} diff --git a/docs/accessanalyzer/1.0/configurations/_category_.json b/docs/accessanalyzer/1.0/configurations/_category_.json index 9b86fef70b..76daee8c8e 100644 --- a/docs/accessanalyzer/1.0/configurations/_category_.json +++ b/docs/accessanalyzer/1.0/configurations/_category_.json @@ -1,5 +1,5 @@ { - "label": "Configurations and Making Changes", + "label": "Configuration", "position": 30, "collapsed": true, "collapsible": true diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/_category_.json b/docs/accessanalyzer/1.0/configurations/configuration-node/_category_.json index d5bca8fd28..70b787ca97 100644 --- a/docs/accessanalyzer/1.0/configurations/configuration-node/_category_.json +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/_category_.json @@ -1,5 +1,5 @@ { - "label": "Configuration Node", + "label": "Settings", "position": 20, "collapsed": true, "collapsible": true diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/application-settings.md b/docs/accessanalyzer/1.0/configurations/configuration-node/application-settings.md index 3aba566106..53382242e1 100644 --- a/docs/accessanalyzer/1.0/configurations/configuration-node/application-settings.md +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/application-settings.md @@ -1,7 +1,7 @@ --- title: "Application Settings" description: "Managing application settings in the Configuration node" -sidebar_position: 60 +sidebar_position: 80 --- # Application Settings diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/logs.md b/docs/accessanalyzer/1.0/configurations/configuration-node/logs.md index b28fd89fbe..88b30332d1 100644 --- a/docs/accessanalyzer/1.0/configurations/configuration-node/logs.md +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/logs.md @@ -1,9 +1,9 @@ --- -title: "Logs" -description: "Viewing logs in the Configuration node" -sidebar_position: 70 +title: "System Logs" +description: "Viewing system logs in Access Analyzer" +sidebar_position: 90 --- -# Logs +# System Logs *Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/notifications.md b/docs/accessanalyzer/1.0/configurations/configuration-node/notifications.md new file mode 100644 index 0000000000..40327ecad5 --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/notifications.md @@ -0,0 +1,9 @@ +--- +title: "Notifications" +description: "Configuring SMTP email notifications in Access Analyzer" +sidebar_position: 100 +--- + +# Notifications + +*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data/_category_.json b/docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data/_category_.json new file mode 100644 index 0000000000..7965ccfb43 --- /dev/null +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Sensitive Data", + "position": 60, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/configurations/mip-labeling-workflow.md b/docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data/mip-labeling.md similarity index 58% rename from docs/accessanalyzer/1.0/configurations/mip-labeling-workflow.md rename to docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data/mip-labeling.md index b28cbd75aa..32bed90184 100644 --- a/docs/accessanalyzer/1.0/configurations/mip-labeling-workflow.md +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data/mip-labeling.md @@ -1,9 +1,9 @@ --- -title: "MIP Labeling and Workflow" +title: "MIP Labeling" description: "Microsoft Information Protection labeling and workflow configuration" -sidebar_position: 30 +sidebar_position: 10 --- -# MIP Labeling and Workflow +# MIP Labeling *Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data.md b/docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data/overview.md similarity index 87% rename from docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data.md rename to docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data/overview.md index 5c5453e455..b1535ed51f 100644 --- a/docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data.md +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data/overview.md @@ -1,7 +1,7 @@ --- title: "Sensitive Data" description: "Managing sensitive data settings in the Configuration node" -sidebar_position: 55 +sidebar_position: 5 --- # Sensitive Data diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/service-accounts.md b/docs/accessanalyzer/1.0/configurations/configuration-node/service-accounts.md index 7ce3e52660..956d4289c2 100644 --- a/docs/accessanalyzer/1.0/configurations/configuration-node/service-accounts.md +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/service-accounts.md @@ -1,7 +1,7 @@ --- title: "Service Accounts" description: "Managing service accounts in the Configuration node" -sidebar_position: 20 +sidebar_position: 10 --- # Service Accounts diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/source-groups.md b/docs/accessanalyzer/1.0/configurations/configuration-node/source-groups.md index d78d64468a..0eab251842 100644 --- a/docs/accessanalyzer/1.0/configurations/configuration-node/source-groups.md +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/source-groups.md @@ -1,7 +1,7 @@ --- title: "Source Groups" description: "Managing source groups in the Configuration node" -sidebar_position: 80 +sidebar_position: 20 --- # Source Groups diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/sources.md b/docs/accessanalyzer/1.0/configurations/configuration-node/sources.md deleted file mode 100644 index f99a43aef2..0000000000 --- a/docs/accessanalyzer/1.0/configurations/configuration-node/sources.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Sources" -description: "Managing sources in the Configuration node" -sidebar_position: 10 ---- - -# Sources - -*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/users.md b/docs/accessanalyzer/1.0/configurations/configuration-node/users.md index c5a0e8191a..50aa57edd1 100644 --- a/docs/accessanalyzer/1.0/configurations/configuration-node/users.md +++ b/docs/accessanalyzer/1.0/configurations/configuration-node/users.md @@ -1,7 +1,7 @@ --- title: "Users" description: "Managing users in the Configuration node" -sidebar_position: 50 +sidebar_position: 70 --- # Users diff --git a/docs/accessanalyzer/1.0/configurations/source-group-changes/_category_.json b/docs/accessanalyzer/1.0/configurations/source-group-changes/_category_.json deleted file mode 100644 index 0b5c8adf0b..0000000000 --- a/docs/accessanalyzer/1.0/configurations/source-group-changes/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Making Changes to Source Group Wizards", - "position": 10, - "collapsed": true, - "collapsible": true -} diff --git a/docs/accessanalyzer/1.0/connectors/activedirectory.md b/docs/accessanalyzer/1.0/connectors/activedirectory.md index 2ef3c03a17..6a2949d4f2 100644 --- a/docs/accessanalyzer/1.0/connectors/activedirectory.md +++ b/docs/accessanalyzer/1.0/connectors/activedirectory.md @@ -6,40 +6,34 @@ sidebar_position: 30 # Active Directory -The Active Directory connector synchronizes users, groups, and group memberships from Active Directory into Access Analyzer. It uses the LDAP protocol for communication. +Access Analyzer scans Active Directory domains to enumerate users, groups, group memberships, permissions, and sensitive data. -## Network Requirements +## Supported Versions -| Port | Protocol | Direction | Description | -| --- | --- | --- | --- | -| 389 | TCP | Access Analyzer → Domain Controller | LDAP | -| 636 | TCP | Access Analyzer → Domain Controller | LDAPS (LDAP over SSL) | +- Windows Server 2016 and later +- Windows 2003 Forest level or higher -## Service Account Requirements +## Domain Controller Requirements -The connector requires a domain service account with the following: +The following must be installed on each domain controller to be scanned: -| Requirement | Details | -| --- | --- | -| **Account type** | Domain user account | -| **Authentication** | Username and password | -| **Minimum permissions** | Read access to directory objects (users, groups, OUs) | -| **Recommended group** | Domain Users (or equivalent read-only access) | +- .NET Framework 4.5 or later +- WINRM Service -:::note -The service account does not require Domain Admin or any write permissions. Read-only access to directory objects is sufficient for identity synchronization. -::: +## Permissions + +- Member of the **Domain Administrators** group -## Credential Type +:::info +Use Domain Administrator or Local Administrator privileges when running Access Analyzer against an Active Directory domain controller. +::: -| Field | Value | -| --- | --- | -| **Type** | Username / Password | -| **Username format** | `DOMAIN\username` or `username@domain.com` | +## Port Requirements -## Connector Capabilities +The following firewall ports are required for the Active Directory connector: -| Operation | Description | -| --- | --- | -| **Test connection** | Validates LDAP connectivity and credential authentication | -| **Sync** | Full synchronization of users, groups, and group memberships | +| Port | Protocol | Description | +| --- | --- | --- | +| 389 | TCP | LDAP | +| 135–139 | TCP | RPC | +| Randomly allocated high TCP ports | TCP | RPC dynamic ports | diff --git a/docs/accessanalyzer/1.0/connectors/entra-id/app-registration-secret.md b/docs/accessanalyzer/1.0/connectors/entra-id/app-registration-secret.md index 789a141560..4c6af18559 100644 --- a/docs/accessanalyzer/1.0/connectors/entra-id/app-registration-secret.md +++ b/docs/accessanalyzer/1.0/connectors/entra-id/app-registration-secret.md @@ -1,9 +1,56 @@ --- -title: "App Registration / Secret Configuration" -description: "Configure app registration and client secret for Entra ID" +title: "Client Secret Configuration" +description: "Configure a client secret for the Entra ID app registration" sidebar_position: 30 --- -# App Registration / Secret Configuration +# Client Secret Configuration -*Content coming soon.* +Access Analyzer authenticates to Microsoft Entra ID using a client secret. The client secret is generated within your registered Microsoft Entra ID application and provided to Access Analyzer when configuring the Entra ID connector. + +For state-in-time data collection, the registered application must also be assigned to the Global Administrator role. + +## Generate Client Secret Value + +**Step 1 –** Sign in to the [Microsoft Entra admin center](https://entra.microsoft.com/). + +**Step 2 –** Navigate to **Identity** > **Applications** > **App registrations**. + +**Step 3 –** Click the **All applications** tab and select your registered application. + +**Step 4 –** Click **Certificates & secrets** under the Manage section. + +**Step 5 –** On the **Client secrets** tab, click **New client secret**. + +**Step 6 –** Specify the following: + +- **Description** – Enter a description for the secret +- **Expires** – Select an expiration period + +**Step 7 –** Click **Add**. The client secret value is displayed in the **Value** column. + +:::warning +Copy the client secret value immediately. Once you navigate away from this page, the value cannot be retrieved and you will need to create a new secret. +::: + +## Assign Roles to the App + +The registered application must be assigned to the **Global Administrator** role for Entra ID state-in-time data collection. + +**Step 1 –** Sign in to the [Microsoft Entra admin center](https://entra.microsoft.com/). + +**Step 2 –** Navigate to **Identity** > **Applications** > **App registrations**. + +**Step 3 –** Click the **All applications** tab and select your registered application. + +**Step 4 –** Click **Roles and administrators** under the Manage section. + +**Step 5 –** On the All roles page, search for **Global Administrator**. + +**Step 6 –** Click the **Global Administrator** role. The Assignments page opens. + +**Step 7 –** Click **Add assignments** in the top toolbar. + +**Step 8 –** Search for and select your registered application. + +**Step 9 –** Click **Add**. The application is listed on the Assignments page. diff --git a/docs/accessanalyzer/1.0/connectors/entra-id/entra-requirements.md b/docs/accessanalyzer/1.0/connectors/entra-id/entra-requirements.md index b2b3c7917a..cc1ab4799f 100644 --- a/docs/accessanalyzer/1.0/connectors/entra-id/entra-requirements.md +++ b/docs/accessanalyzer/1.0/connectors/entra-id/entra-requirements.md @@ -1,9 +1,69 @@ --- -title: "Setting Up Requirements Within Entra" +title: "Entra Tenant Requirements" description: "Configure Entra ID requirements for connectivity" sidebar_position: 20 --- -# Setting Up Requirements Within Entra +# Entra Tenant Requirements -*Content coming soon.* +Access Analyzer connects to Microsoft Entra ID via a registered application using modern authentication, including support for multi-factor authentication (MFA). Access Analyzer accesses Entra ID through Microsoft Graph and other modern APIs, authenticated through a pre-configured Microsoft Entra ID application with the appropriate permissions. + +You must register a dedicated Microsoft Entra ID application for Access Analyzer and grant it the required permissions before adding Entra ID as a data source. + +:::note +A user account with the Global Administrator, Application Administrator, or Cloud Application Administrator role is required to register an application and grant admin consent for permissions. +::: + +:::note +The registered application must be assigned to the **Global Administrator** role for state-in-time data collection. +::: + +## Register an App in Microsoft Entra ID + +**Step 1 –** Sign in to the [Microsoft Entra admin center](https://entra.microsoft.com/). + +**Step 2 –** On the left navigation menu, navigate to **Identity** > **Applications** > **App registrations**. + +**Step 3 –** On the App registrations page, click **New registration** in the top toolbar. + +**Step 4 –** Specify the following on the Register an application page: + +- **Name** – Enter a display name for the application, for example, *Access Analyzer Entra ID* +- **Supported account types** – Select **Accounts in this organizational directory only** +- **Redirect URI (optional)** – Leave blank + +**Step 5 –** Click **Register**. + +The Overview page for the newly registered application opens. Note the following values — you will need them when configuring the Entra ID connector in Access Analyzer: + +- **Application (client) ID** +- **Directory (tenant) ID** + +## Grant Permissions to the App + +**Step 1 –** Sign in to the [Microsoft Entra admin center](https://entra.microsoft.com/). + +**Step 2 –** Navigate to **Identity** > **Applications** > **App registrations**. + +**Step 3 –** Click the **All applications** tab and select the application you registered. + +**Step 4 –** Click **API permissions** under the Manage section. + +**Step 5 –** Click **Add a permission**. The Request API permissions pane opens. + +**Step 6 –** Click an API to access its permissions, then click the **Application permissions** tab. + +**Step 7 –** Select the required permissions for each API (see table below). + +**Step 8 –** Click **Add Permissions**. + +**Step 9 –** Repeat Steps 6–8 for each API listed in the table below. + +**Step 10 –** Click **Grant admin consent for ``** to apply the permissions. + +### Required Permissions + +| API | Permission | Description | +| --- | --- | --- | +| Microsoft Graph | Directory.Read.All | Read directory data | +| Microsoft Graph | Policy.Read.All | Read your organization's policies (required for state-in-time reports) | diff --git a/docs/accessanalyzer/1.0/connectors/entra-id/overview.md b/docs/accessanalyzer/1.0/connectors/entra-id/overview.md index 11dfb77943..c807dd797d 100644 --- a/docs/accessanalyzer/1.0/connectors/entra-id/overview.md +++ b/docs/accessanalyzer/1.0/connectors/entra-id/overview.md @@ -1,10 +1,10 @@ --- -title: "Entra ID" +title: "Entra ID Requirements" description: "Azure App Registration, Graph API permissions, and OAuth2 credentials" sidebar_position: 40 --- -# Entra ID +# Entra ID Requirements The Entra ID connector validates connectivity to Microsoft Entra ID (formerly Azure Active Directory) using OAuth2 client credentials. diff --git a/docs/accessanalyzer/1.0/connectors/file-servers/cifs.md b/docs/accessanalyzer/1.0/connectors/file-servers/cifs.md index a5ade15dbd..e4ceab825e 100644 --- a/docs/accessanalyzer/1.0/connectors/file-servers/cifs.md +++ b/docs/accessanalyzer/1.0/connectors/file-servers/cifs.md @@ -6,47 +6,48 @@ sidebar_position: 10 # CIFS / SMB File Share -The CIFS/SMB connector scans Windows file shares to enumerate files, folders, and access permissions. It supports SMBv2 and SMBv3 protocols with concurrent scanning workers. +Access Analyzer scans Windows file servers to enumerate files, folders, access permissions, and sensitive data. -## Network Requirements +Scanning can be performed directly from the Access Analyzer service (local mode) or via Scanners — Kubernetes-deployed containers for distributed scanning of remote environments. See the [Utilizing Scanners](../../scanners/overview.md) section for details on Scanner architecture. -| Port | Protocol | Direction | Description | -| --- | --- | --- | --- | -| 445 | TCP | Access Analyzer → File Server | SMB file sharing | +## Permissions -## Service Account Requirements +Configure the service account credential with the following rights on the target Windows host(s): -| Requirement | Details | -| --- | --- | -| **Account type** | Domain or local user account on the file server | -| **Authentication** | Username and password | -| **Minimum permissions** | Read access and list permissions on target shares | -| **Domain** | Required if the file server is domain-joined | +- Group membership in both of the following local groups: + - **Power Users** + - **Backup Operators** +- Granted the **Backup files and directories** local policy privilege +- Granted the **Network access: Restrict clients allowed to make remote calls to SAM** Local Policies > Security Options privilege :::note -The service account needs read-only access to the shares and folders being scanned. It does not require write, modify, or administrative permissions. +To collect data on administrative shares and local policies for a Windows target, the credential must have group membership in the local **Administrators** group. ::: -## Credential Type +## Windows File System Clusters -| Field | Value | -| --- | --- | -| **Type** | Username / Password | -| **Username format** | `DOMAIN\username` or local account name | +When targeting a Windows File System Cluster, permissions must be configured on all nodes that comprise the cluster. Additional requirements beyond the standard permissions above: -## Connector Capabilities +- Remote Registry Service must be enabled on all cluster nodes +- Group membership in the local **Administrators** group +- Granted the **Log on as a batch** privilege -| Operation | Description | -| --- | --- | -| **Test connection** | Validates SMB connectivity and authentication | -| **Access scan** | Enumerates files, folders, and permissions with configurable worker concurrency (1–20) | -| **Get object** | Retrieves specific file or folder metadata | +:::note +Target the Windows Cluster File Server Role Server (the name clients connect to) when running a File System scan against a Windows File System Cluster. +::: + +## DFS Namespaces + +For domain-based DFS namespaces, the scan is configured to target the default domain controller for the domain. For standalone namespaces or multiple namespaces, target the server(s) hosting the namespace(s) directly. + +If the DFS hosting server is part of a Windows Cluster, the Windows File System Cluster requirements above also apply. + +## Sensitive Data Discovery + +Sensitive Data Discovery (SDD) scans require **.NET Framework 4.7.2 or later** installed on the server being scanned. -## Scan Configuration Options +## Port Requirements -| Option | Description | -| --- | --- | -| **Share filtering** | Include or exclude specific shares | -| **Scan depth** | Maximum folder depth to traverse | -| **Worker concurrency** | Number of parallel scanning threads (1–20) | -| **Pause / Resume** | Scans can be paused and resumed | +| Port | Protocol | Description | +| --- | --- | --- | +| 445 | TCP | SMB file sharing | diff --git a/docs/accessanalyzer/1.0/connectors/sharepoint-online/azure-permissions.md b/docs/accessanalyzer/1.0/connectors/sharepoint-online/azure-permissions.md index da88304a7a..b474d46faa 100644 --- a/docs/accessanalyzer/1.0/connectors/sharepoint-online/azure-permissions.md +++ b/docs/accessanalyzer/1.0/connectors/sharepoint-online/azure-permissions.md @@ -1,9 +1,66 @@ --- -title: "Setting Up Requirements Within Entra" -description: "Configure Entra ID requirements for SharePoint Online connectivity" +title: "App Permissions in Entra" +description: "Configure Entra ID app permissions for SharePoint Online connectivity" sidebar_position: 10 --- -# Setting Up Requirements Within Entra +# App Permissions in Entra -*Content coming soon.* +Access Analyzer connects to SharePoint Online via a Microsoft Entra ID registered application using modern authentication, including support for multi-factor authentication (MFA). Access Analyzer accesses SharePoint Online through Microsoft Graph and other modern APIs, authenticated through a pre-configured Microsoft Entra ID application with the appropriate permissions. + +You must register a dedicated Microsoft Entra ID application for Access Analyzer and grant it the required permissions before adding SharePoint Online as a data source. + +:::note +A user account with the Global Administrator, Application Administrator, or Cloud Application Administrator role is required to register an application and grant admin consent for permissions. +::: + +## Register an App in Microsoft Entra ID + +**Step 1 –** Sign in to the [Microsoft Entra admin center](https://entra.microsoft.com/). + +**Step 2 –** On the left navigation menu, navigate to **Identity** > **Applications** > **App registrations**. + +**Step 3 –** On the App registrations page, click **New registration** in the top toolbar. + +**Step 4 –** Specify the following on the Register an application page: + +- **Name** – Enter a display name for the application, for example, *Access Analyzer SharePoint Online* +- **Supported account types** – Select **Accounts in this organizational directory only** +- **Redirect URI (optional)** – Leave blank + +**Step 5 –** Click **Register**. + +The Overview page for the newly registered application opens. Note the following values — you will need them when configuring the SharePoint Online connector in Access Analyzer: + +- **Application (client) ID** +- **Directory (tenant) ID** + +## Grant Permissions to the App + +**Step 1 –** Sign in to the [Microsoft Entra admin center](https://entra.microsoft.com/). + +**Step 2 –** Navigate to **Identity** > **Applications** > **App registrations**. + +**Step 3 –** Click the **All applications** tab and select the application you registered. + +**Step 4 –** Click **API permissions** under the Manage section. + +**Step 5 –** Click **Add a permission**. The Request API permissions pane opens. + +**Step 6 –** Click an API to access its permissions, then click the **Application permissions** tab. + +**Step 7 –** Select the required permissions for each API (see table below). + +**Step 8 –** Click **Add Permissions**. + +**Step 9 –** Repeat Steps 6–8 for each API listed in the table below. + +**Step 10 –** Click **Grant admin consent for ``** to apply the permissions. + +### Required Permissions + +| API | Permission | Description | +| --- | --- | --- | +| Microsoft Graph | Sites.Read.All | Read items in all site collections | +| Microsoft Graph | Directory.Read.All | Read directory data | +| SharePoint | Sites.FullControl.All | Full control of all site collections (required for permissions and state-in-time reports) | diff --git a/docs/accessanalyzer/1.0/connectors/sharepoint-online/tenant-certificate-config.md b/docs/accessanalyzer/1.0/connectors/sharepoint-online/tenant-certificate-config.md index b702b388e5..2cdeeda634 100644 --- a/docs/accessanalyzer/1.0/connectors/sharepoint-online/tenant-certificate-config.md +++ b/docs/accessanalyzer/1.0/connectors/sharepoint-online/tenant-certificate-config.md @@ -1,9 +1,59 @@ --- -title: "App Registration / Certificate Configuration" -description: "Configure app registration and certificate authentication for SharePoint Online" +title: "Certificate Configuration" +description: "Configure certificate authentication for the SharePoint Online app registration" sidebar_position: 20 --- -# App Registration / Certificate Configuration +# Certificate Configuration -*Content coming soon.* +Access Analyzer uses two authentication methods depending on the SharePoint Online scan type: + +- **Client Secret** — used for access and permissions scanning +- **Certificate** — required for state-in-time (permissions snapshot) scanning + +Both are configured within your registered Microsoft Entra ID application. + +## Generate Client Secret Value + +**Step 1 –** Sign in to the [Microsoft Entra admin center](https://entra.microsoft.com/). + +**Step 2 –** Navigate to **Identity** > **Applications** > **App registrations**. + +**Step 3 –** Click the **All applications** tab and select your registered application. + +**Step 4 –** Click **Certificates & secrets** under the Manage section. + +**Step 5 –** On the **Client secrets** tab, click **New client secret**. + +**Step 6 –** Specify the following: + +- **Description** – Enter a description for the secret +- **Expires** – Select an expiration period + +**Step 7 –** Click **Add**. The client secret value is displayed in the **Value** column. + +:::warning +Copy the client secret value immediately. Once you navigate away from this page, the value cannot be retrieved and you will need to create a new secret. +::: + +## Upload a Certificate + +**Step 1 –** Sign in to the [Microsoft Entra admin center](https://entra.microsoft.com/). + +**Step 2 –** Navigate to **Identity** > **Applications** > **App registrations**. + +**Step 3 –** Click the **All applications** tab and select your registered application. + +**Step 4 –** Click **Certificates & secrets** under the Manage section. + +**Step 5 –** Click the **Certificates** tab. + +**Step 6 –** Click **Upload certificate**. + +**Step 7 –** Click the file icon next to the **Select a File** field. + +**Step 8 –** Browse to and select your certificate file (.cer or .pem), then click **Open**. + +**Step 9 –** Enter a description for the certificate. + +**Step 10 –** Click **Add**. The certificate is uploaded to the registered application. diff --git a/docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-reports.md b/docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-reports.md deleted file mode 100644 index 3070386614..0000000000 --- a/docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-reports.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "How to Analyze Reports" -description: "Guide to analyzing reports in Access Analyzer" -sidebar_position: 20 ---- - -# How to Analyze Reports - -*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-the-data.md b/docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-the-data.md index c6dbb29a93..de949167e3 100644 --- a/docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-the-data.md +++ b/docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-the-data.md @@ -1,9 +1,9 @@ --- -title: "How to Analyze the Data" -description: "Guide to analyzing data using dashboards in Access Analyzer" +title: "Analyzing Data and Reports" +description: "Guide to analyzing data and reports in Access Analyzer" sidebar_position: 10 --- -# How to Analyze the Data +# Analyzing Data and Reports *Content coming soon.* diff --git a/docs/accessanalyzer/1.0/gettingstarted/_category_.json b/docs/accessanalyzer/1.0/gettingstarted/_category_.json index 1c9c947f1d..3cefeac060 100644 --- a/docs/accessanalyzer/1.0/gettingstarted/_category_.json +++ b/docs/accessanalyzer/1.0/gettingstarted/_category_.json @@ -1,5 +1,5 @@ { - "label": "Start Collecting Data", + "label": "Quick Start Guides", "position": 20, "collapsed": true, "collapsible": true diff --git a/docs/accessanalyzer/1.0/gettingstarted/active-directory-sync.md b/docs/accessanalyzer/1.0/gettingstarted/active-directory-sync.md deleted file mode 100644 index 55ac39164a..0000000000 --- a/docs/accessanalyzer/1.0/gettingstarted/active-directory-sync.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Setting Up My First Active Directory Sync" -description: "Connect to Active Directory and sync users, groups, and organizational units" -sidebar_position: 20 ---- - -# Setting Up My First Active Directory Sync - -*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/gettingstarted/active-directory-sync/_category_.json b/docs/accessanalyzer/1.0/gettingstarted/active-directory-sync/_category_.json new file mode 100644 index 0000000000..fc2c06370c --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/active-directory-sync/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Scanning Active Directory", + "position": 20, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/configurations/source-group-changes/active-directory.md b/docs/accessanalyzer/1.0/gettingstarted/active-directory-sync/active-directory.md similarity index 100% rename from docs/accessanalyzer/1.0/configurations/source-group-changes/active-directory.md rename to docs/accessanalyzer/1.0/gettingstarted/active-directory-sync/active-directory.md diff --git a/docs/accessanalyzer/1.0/gettingstarted/activity-data/_category_.json b/docs/accessanalyzer/1.0/gettingstarted/activity-data/_category_.json index 188fff07b8..e008bc29bf 100644 --- a/docs/accessanalyzer/1.0/gettingstarted/activity-data/_category_.json +++ b/docs/accessanalyzer/1.0/gettingstarted/activity-data/_category_.json @@ -1,5 +1,5 @@ { - "label": "Start Collecting Activity Data", + "label": "Collecting Activity Data", "position": 70, "collapsed": true, "collapsible": true diff --git a/docs/accessanalyzer/1.0/gettingstarted/activity-monitor-integration/_category_.json b/docs/accessanalyzer/1.0/gettingstarted/activity-monitor-integration/_category_.json new file mode 100644 index 0000000000..130074f727 --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/activity-monitor-integration/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Activity Monitor Integration", + "position": 80, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/activity-monitor-integration/overview.md b/docs/accessanalyzer/1.0/gettingstarted/activity-monitor-integration/overview.md similarity index 58% rename from docs/accessanalyzer/1.0/activity-monitor-integration/overview.md rename to docs/accessanalyzer/1.0/gettingstarted/activity-monitor-integration/overview.md index 21dd6869e7..b76c72252c 100644 --- a/docs/accessanalyzer/1.0/activity-monitor-integration/overview.md +++ b/docs/accessanalyzer/1.0/gettingstarted/activity-monitor-integration/overview.md @@ -1,9 +1,9 @@ --- -title: "Setting up Activity Monitor Integration" +title: "Activity Monitor Integration" description: "Configure Activity Monitor integration with Access Analyzer" sidebar_position: 10 --- -# Setting up Activity Monitor Integration +# Activity Monitor Integration *Content coming soon.* diff --git a/docs/accessanalyzer/1.0/gettingstarted/entra-id-sync.md b/docs/accessanalyzer/1.0/gettingstarted/entra-id-sync.md deleted file mode 100644 index 031773a286..0000000000 --- a/docs/accessanalyzer/1.0/gettingstarted/entra-id-sync.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Setting Up My First Entra ID Sync" -description: "Connect to Microsoft Entra ID and sync cloud identities" -sidebar_position: 40 ---- - -# Setting Up My First Entra ID Sync - -*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/gettingstarted/entra-id-sync/_category_.json b/docs/accessanalyzer/1.0/gettingstarted/entra-id-sync/_category_.json new file mode 100644 index 0000000000..b4785d5d62 --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/entra-id-sync/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Scanning Entra ID", + "position": 40, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/configurations/source-group-changes/entra-id.md b/docs/accessanalyzer/1.0/gettingstarted/entra-id-sync/entra-id.md similarity index 100% rename from docs/accessanalyzer/1.0/configurations/source-group-changes/entra-id.md rename to docs/accessanalyzer/1.0/gettingstarted/entra-id-sync/entra-id.md diff --git a/docs/accessanalyzer/1.0/gettingstarted/file-server-scans.md b/docs/accessanalyzer/1.0/gettingstarted/file-server-scans.md deleted file mode 100644 index e99a39cb05..0000000000 --- a/docs/accessanalyzer/1.0/gettingstarted/file-server-scans.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Setting Up My First File Server Scans" -description: "Scan CIFS/SMB file shares for permissions and sensitive data" -sidebar_position: 30 ---- - -# Setting Up My First File Server Scans - -*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/gettingstarted/file-server-scans/_category_.json b/docs/accessanalyzer/1.0/gettingstarted/file-server-scans/_category_.json new file mode 100644 index 0000000000..4771d2c62e --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/file-server-scans/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Scanning File Servers", + "position": 30, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/configurations/source-group-changes/file-server.md b/docs/accessanalyzer/1.0/gettingstarted/file-server-scans/file-server.md similarity index 100% rename from docs/accessanalyzer/1.0/configurations/source-group-changes/file-server.md rename to docs/accessanalyzer/1.0/gettingstarted/file-server-scans/file-server.md diff --git a/docs/accessanalyzer/1.0/gettingstarted/first-service-account.md b/docs/accessanalyzer/1.0/gettingstarted/first-service-account.md index 124d4ff6bb..f58efefd6c 100644 --- a/docs/accessanalyzer/1.0/gettingstarted/first-service-account.md +++ b/docs/accessanalyzer/1.0/gettingstarted/first-service-account.md @@ -1,9 +1,9 @@ --- -title: "Setting Up My First Service Account" -description: "Create your first service account to connect to data sources" +title: "Setting Up a Service Account" +description: "Create a service account to connect to data sources" sidebar_position: 1 --- -# Setting Up My First Service Account +# Setting Up a Service Account *Content coming soon.* diff --git a/docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan.md b/docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan.md deleted file mode 100644 index e831c710c1..0000000000 --- a/docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Setting Up My First SharePoint Online Scan" -description: "Scan SharePoint Online sites for permissions and sensitive data" -sidebar_position: 50 ---- - -# Setting Up My First SharePoint Online Scan - -*Content coming soon.* diff --git a/docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan/_category_.json b/docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan/_category_.json new file mode 100644 index 0000000000..23057cd793 --- /dev/null +++ b/docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Scanning SharePoint Online", + "position": 50, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/configurations/source-group-changes/sharepoint-online.md b/docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan/sharepoint-online.md similarity index 100% rename from docs/accessanalyzer/1.0/configurations/source-group-changes/sharepoint-online.md rename to docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan/sharepoint-online.md diff --git a/docs/accessanalyzer/1.0/gettingstarted/source-group-wizard.md b/docs/accessanalyzer/1.0/gettingstarted/source-group-wizard.md index a78450039d..ece698c97b 100644 --- a/docs/accessanalyzer/1.0/gettingstarted/source-group-wizard.md +++ b/docs/accessanalyzer/1.0/gettingstarted/source-group-wizard.md @@ -1,9 +1,9 @@ --- -title: "Understanding the Source Group Wizard Workflow" -description: "Learn how the Source Group Wizard guides you through connecting data sources and configuring scans" +title: "Source Group Wizard" +description: "How the Source Group Wizard guides you through connecting data sources and configuring scans" sidebar_position: 10 --- -# Understanding the Source Group Wizard Workflow +# Source Group Wizard *Content coming soon.* diff --git a/docs/accessanalyzer/1.0/install/_category_.json b/docs/accessanalyzer/1.0/install/_category_.json index edb97672cd..4ec6b4da75 100644 --- a/docs/accessanalyzer/1.0/install/_category_.json +++ b/docs/accessanalyzer/1.0/install/_category_.json @@ -1,6 +1,6 @@ { "label": "Installation", - "position": 16, + "position": 12, "collapsed": true, "collapsible": true } diff --git a/docs/accessanalyzer/1.0/install/system/_category_.json b/docs/accessanalyzer/1.0/install/system/_category_.json new file mode 100644 index 0000000000..3ca820d9a9 --- /dev/null +++ b/docs/accessanalyzer/1.0/install/system/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "System Requirements", + "position": 5, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/1.0/system/kubernetes.md b/docs/accessanalyzer/1.0/install/system/kubernetes.md similarity index 100% rename from docs/accessanalyzer/1.0/system/kubernetes.md rename to docs/accessanalyzer/1.0/install/system/kubernetes.md diff --git a/docs/accessanalyzer/1.0/system/network.md b/docs/accessanalyzer/1.0/install/system/network.md similarity index 100% rename from docs/accessanalyzer/1.0/system/network.md rename to docs/accessanalyzer/1.0/install/system/network.md diff --git a/docs/accessanalyzer/1.0/system/requirements.md b/docs/accessanalyzer/1.0/install/system/requirements.md similarity index 100% rename from docs/accessanalyzer/1.0/system/requirements.md rename to docs/accessanalyzer/1.0/install/system/requirements.md diff --git a/docs/accessanalyzer/1.0/scanners/_category_.json b/docs/accessanalyzer/1.0/scanners/_category_.json index 06591067c1..1f2304bcca 100644 --- a/docs/accessanalyzer/1.0/scanners/_category_.json +++ b/docs/accessanalyzer/1.0/scanners/_category_.json @@ -1,5 +1,5 @@ { - "label": "Utilizing Scanners", + "label": "Scanners", "position": 40, "collapsed": true, "collapsible": true diff --git a/docs/accessanalyzer/1.0/scanners/best-practices.md b/docs/accessanalyzer/1.0/scanners/best-practices.md index 01fabacf57..be4a4c9af6 100644 --- a/docs/accessanalyzer/1.0/scanners/best-practices.md +++ b/docs/accessanalyzer/1.0/scanners/best-practices.md @@ -1,9 +1,9 @@ --- -title: "Best Practices" +title: "Scanner Best Practices" description: "Best practices for configuring and running scanners in Access Analyzer" sidebar_position: 20 --- -# Best Practices +# Scanner Best Practices *Content coming soon.* diff --git a/docs/accessanalyzer/1.0/scanners/overview.md b/docs/accessanalyzer/1.0/scanners/overview.md index 2c3087426a..aa46eb4e4c 100644 --- a/docs/accessanalyzer/1.0/scanners/overview.md +++ b/docs/accessanalyzer/1.0/scanners/overview.md @@ -6,4 +6,29 @@ sidebar_position: 10 # Overview of Scanners -*Content coming soon.* +Scanners are lightweight, containerized agents used by Access Analyzer to perform distributed scanning of remote environments. They eliminate the need for a traditional proxy server by leveraging the Kubernetes infrastructure already powering Access Analyzer. + +## Supported Connectors + +Scanners are available for the following connectors only: + +- **Active Directory** +- **Windows File Servers** + +All other connectors (Entra ID, SharePoint Online) connect directly from the Access Analyzer service and do not use Scanners. + +## Architecture + +Scanners run as Kubernetes Jobs — short-lived containers that are deployed on demand to perform a scan and then terminated. This is a fundamentally different architecture from the Proxy and Applet modes available in legacy Netwrix Access Analyzer (NAA) v12. There is no persistent agent process and no manual applet deployment. + +| | Legacy NAA (v12) | Access Analyzer v1.0 | +| --- | --- | --- | +| **Distributed scanning** | Proxy server / Applet deployment | Kubernetes-deployed Scanner containers | +| **Deployment model** | Manual, persistent agent | On-demand Kubernetes Jobs | +| **Supported targets** | All file system types | Active Directory, Windows File Servers | + +## Pending Documentation + +:::note +Detailed Scanner configuration steps, deployment prerequisites, and architecture diagrams are pending input from the development team and will be added to this section prior to GA release. +::: diff --git a/docs/accessanalyzer/1.0/system/_category_.json b/docs/accessanalyzer/1.0/system/_category_.json deleted file mode 100644 index 684c03e579..0000000000 --- a/docs/accessanalyzer/1.0/system/_category_.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "label": "System Requirements", - "position": 12, - "collapsed": true, - "collapsible": true, - "link": { - "type": "doc", - "id": "kubernetes" - } -} From 4d5d7b3fb063dedb9e228a1ee73e589d7378a23c Mon Sep 17 00:00:00 2001 From: carlos-mejia_nwx Date: Tue, 7 Apr 2026 15:55:45 -0400 Subject: [PATCH 18/62] AA26: Update install guides with complete outbound domain list Expand the outbound endpoint tables in network.md and quickinstall.md from 4 incomplete rows to the full 18 required domains, grouped by category (Keygen/Licensing, GitHub, Docker Hub/CDN, K3s/Rancher) with When Required column. Add Required Domains section to quickinstall.md so the quick guide is self-contained. Co-Authored-By: Claude Sonnet 4.6 --- .../1.0/install/quickinstall.md | 27 ++++++++++++- .../1.0/install/system/network.md | 40 ++++++++++++++----- 2 files changed, 55 insertions(+), 12 deletions(-) diff --git a/docs/accessanalyzer/1.0/install/quickinstall.md b/docs/accessanalyzer/1.0/install/quickinstall.md index f3e9e35808..334c741b52 100644 --- a/docs/accessanalyzer/1.0/install/quickinstall.md +++ b/docs/accessanalyzer/1.0/install/quickinstall.md @@ -18,13 +18,38 @@ Before running the installer, confirm the following: | **Memory** | 8 GB RAM | 16 GB RAM | | **CPU** | 2 vCPUs | 4 vCPUs | | **Disk Space** | 20 GB free | 50 GB free | -| **Network** | Outbound HTTPS (port 443) | — | +| **Network** | Outbound HTTPS (port 443) to required endpoints — see [Required Domains](#required-domains) below | — | | **License** | Valid Netwrix license key | — | :::note If running on a hypervisor, configure **static memory allocation** (not dynamic/ballooned memory). See [Hardware and System Requirements](/docs/accessanalyzer/1_0/install/requirements) for hypervisor-specific instructions. ::: +## Required Domains + +All endpoints use HTTPS (port 443). The following domains must be reachable from the Access Analyzer server before installation. For firewall rule examples, see [Network and Port Requirements](/docs/accessanalyzer/1_0/install/system/network). + +| Endpoint | Category | Purpose | When Required | +| --- | --- | --- | --- | +| `api.keygen.sh` | Keygen / Licensing | License validation API | Installation and updates | +| `oci.pkg.keygen.sh` | Keygen / Licensing | Netwrix OCI registry — Helm charts and application images | Installation and updates | +| `raw.pkg.keygen.sh` | Keygen / Licensing | Installer script download | Installation and updates | +| `keygen-dist.c3c9112df8df715f42d1162cdce5dba1.r2.cloudflarestorage.com` | Keygen / Licensing CDN | Keygen artifact storage | Installation and updates | +| `api.github.com` | GitHub | GitHub API | Installation only | +| `github.com` | GitHub | Repository and release access | Installation only | +| `raw.githubusercontent.com` | GitHub | ArgoCD bootstrap manifests | Installation only | +| `release-assets.githubusercontent.com` | GitHub | Release asset downloads | Installation only | +| `pkg-containers.githubusercontent.com` | GitHub Container Registry | GitHub Packages CDN | Installation and updates | +| `ghcr.io` | GitHub Container Registry | Container images | Installation and updates | +| `auth.docker.io` | Docker Hub | Docker authentication | Installation and updates | +| `registry-1.docker.io` | Docker Hub | Container images | Installation and updates | +| `production.cloudflare.docker.com` | Docker CDN | Docker Hub CDN | Installation and updates | +| `docker-images-prod.6aa30f8b08e16409b46e0173d6de2f56.r2.cloudflarestorage.com` | Docker CDN | Docker image storage | Installation and updates | +| `d2glxqk2uabbnd.cloudfront.net` | Docker CDN | Docker image CDN | Installation and updates | +| `get.k3s.io` | K3s / Rancher | K3s installer download | Installation only | +| `rpm.rancher.io` | K3s / Rancher | K3s package repository | Installation only | +| `storage.googleapis.com` | K3s / Rancher | K3s artifact storage | Installation only | + ## Step 1: Prepare the System Update the operating system and verify internet connectivity: diff --git a/docs/accessanalyzer/1.0/install/system/network.md b/docs/accessanalyzer/1.0/install/system/network.md index f3c04090b4..8643ce201b 100644 --- a/docs/accessanalyzer/1.0/install/system/network.md +++ b/docs/accessanalyzer/1.0/install/system/network.md @@ -10,14 +10,28 @@ Access Analyzer requires outbound internet access during installation and operat ## Outbound Endpoints (Internet) -The following endpoints must be reachable over HTTPS (port 443): +All outbound traffic uses HTTPS (port 443). The following endpoints must be reachable from the Access Analyzer server: -| Endpoint | Purpose | When Required | -| --- | --- | --- | -| `get.k3s.io` | K3s installer download | Installation only | -| `raw.githubusercontent.com` | ArgoCD manifests | Installation only | -| `oci.pkg.keygen.sh` | Netwrix OCI registry (Helm charts, application images) | Installation and updates | -| `docker.io` / `docker.com` | Container base images | Installation and updates | +| Endpoint | Category | Purpose | When Required | +| --- | --- | --- | --- | +| `api.keygen.sh` | Keygen / Licensing | License validation API | Installation and updates | +| `oci.pkg.keygen.sh` | Keygen / Licensing | Netwrix OCI registry — Helm charts and application images | Installation and updates | +| `raw.pkg.keygen.sh` | Keygen / Licensing | Installer script download | Installation and updates | +| `keygen-dist.c3c9112df8df715f42d1162cdce5dba1.r2.cloudflarestorage.com` | Keygen / Licensing CDN | Keygen artifact storage | Installation and updates | +| `api.github.com` | GitHub | GitHub API | Installation only | +| `github.com` | GitHub | Repository and release access | Installation only | +| `raw.githubusercontent.com` | GitHub | ArgoCD bootstrap manifests | Installation only | +| `release-assets.githubusercontent.com` | GitHub | Release asset downloads | Installation only | +| `pkg-containers.githubusercontent.com` | GitHub Container Registry | GitHub Packages CDN | Installation and updates | +| `ghcr.io` | GitHub Container Registry | Container images | Installation and updates | +| `auth.docker.io` | Docker Hub | Docker authentication | Installation and updates | +| `registry-1.docker.io` | Docker Hub | Container images | Installation and updates | +| `production.cloudflare.docker.com` | Docker CDN | Docker Hub CDN | Installation and updates | +| `docker-images-prod.6aa30f8b08e16409b46e0173d6de2f56.r2.cloudflarestorage.com` | Docker CDN | Docker image storage | Installation and updates | +| `d2glxqk2uabbnd.cloudfront.net` | Docker CDN | Docker image CDN | Installation and updates | +| `get.k3s.io` | K3s / Rancher | K3s installer download | Installation only | +| `rpm.rancher.io` | K3s / Rancher | K3s package repository | Installation only | +| `storage.googleapis.com` | K3s / Rancher | K3s artifact storage | Installation only | ## Internal Ports @@ -41,13 +55,17 @@ All internal ports are bound to the local cluster network. Only port 443 (Traefi Depending on the connectors you configure, the Access Analyzer VM must also have outbound access to your data sources: -| Connector | Target Port | Protocol | Notes | +| Connector | Port | Protocol | Notes | | --- | --- | --- | --- | -| CIFS / SMB | 445 | TCP | SMB file shares | -| Active Directory | 389 / 636 | TCP | LDAP / LDAPS | +| CIFS / SMB | 445 | TCP | SMB file sharing | +| Active Directory | 389 | TCP | LDAP | +| Active Directory | 636 | TCP | LDAPS (encrypted) | +| Active Directory | 135–139 | TCP | RPC | +| Active Directory | 49152–65535 | TCP | RPC dynamic ports | | SharePoint Online | 443 | TCP | Microsoft Graph API | | Entra ID | 443 | TCP | Microsoft identity platform | -| Local Groups | 5985 / 5986 | TCP | WinRM (HTTP / HTTPS) | +| Local Groups | 5985 | TCP | WinRM (HTTP) | +| Local Groups | 5986 | TCP | WinRM (HTTPS) | ## Proxy Configuration From 070f7746b57fea75f5aff4f51a4c18b381e1698d Mon Sep 17 00:00:00 2001 From: carlos-mejia_nwx Date: Tue, 7 Apr 2026 22:44:28 -0400 Subject: [PATCH 19/62] Rename Access Analyzer version from 1.0 to 2601 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Rename docs/accessanalyzer/1.0/ → docs/accessanalyzer/2601/ - Rename sidebars/accessanalyzer/1.0.js → sidebars/accessanalyzer/2601.js - Update version/label/sidebarFile in src/config/products.js - Update kb_allowlist.json entry for accessanalyzer Co-Authored-By: Claude Sonnet 4.6 --- .../configurations/_category_.json | 0 .../configuration-node/_category_.json | 0 .../application-settings.md | 0 .../configurations/configuration-node/logs.md | 0 .../configuration-node/notifications.md | 0 .../configuration-node/scan-executions.md | 0 .../configuration-node/scans.md | 0 .../sensitive-data/_category_.json | 0 .../sensitive-data/mip-labeling.md | 0 .../sensitive-data/overview.md | 0 .../configuration-node/service-accounts.md | 0 .../configuration-node/source-groups.md | 0 .../configuration-node/users.md | 0 .../{1.0 => 2601}/connectors/_category_.json | 0 .../connectors/activedirectory.md | 0 .../connectors/entra-id/_category_.json | 0 .../entra-id/app-registration-secret.md | 0 .../connectors/entra-id/entra-requirements.md | 0 .../connectors/entra-id/overview.md | 0 .../connectors/file-servers/_category_.json | 0 .../connectors/file-servers/celerra.md | 0 .../connectors/file-servers/cifs.md | 0 .../connectors/file-servers/netapp.md | 0 .../connectors/file-servers/unity.md | 0 .../connectors/file-servers/vnx.md | 0 .../sharepoint-online/_category_.json | 0 .../sharepoint-online/azure-permissions.md | 0 .../tenant-certificate-config.md | 0 .../dashboards-reports/_category_.json | 0 .../_category_.json | 0 .../active-directory-dashboard/overview.md | 0 .../data-security-dashboard/_category_.json | 0 .../data-security-dashboard/activity.md | 0 .../data-security-dashboard/overview.md | 0 .../how-to-analyze-the-data.md | 0 .../dashboards-reports/my-reports.md | 0 .../gettingstarted/_category_.json | 0 .../active-directory-sync/_category_.json | 0 .../active-directory-sync/active-directory.md | 0 .../activity-data/_category_.json | 0 .../activity-data/file-server-activity.md | 0 .../_category_.json | 0 .../activity-monitor-integration/overview.md | 0 .../entra-id-sync/_category_.json | 0 .../gettingstarted/entra-id-sync/entra-id.md | 0 .../file-server-scans/_category_.json | 0 .../file-server-scans/file-server.md | 0 .../gettingstarted/first-service-account.md | 0 .../sharepoint-online-scan/_category_.json | 0 .../sharepoint-online.md | 0 .../gettingstarted/source-group-wizard.md | 0 docs/accessanalyzer/{1.0 => 2601}/index.md | 0 .../{1.0 => 2601}/install/_category_.json | 0 .../{1.0 => 2601}/install/postinstall.md | 0 .../{1.0 => 2601}/install/quickinstall.md | 0 .../{1.0 => 2601}/install/security.md | 0 .../install/system/_category_.json | 0 .../install/system/kubernetes.md | 0 .../{1.0 => 2601}/install/system/network.md | 63 ++++++++++++++++++- .../install/system/requirements.md | 14 +++-- .../{1.0 => 2601}/install/uninstall.md | 0 .../{1.0 => 2601}/overview/_category_.json | 0 .../{1.0 => 2601}/overview/keyconcepts.md | 0 .../{1.0 => 2601}/scanners/_category_.json | 0 .../{1.0 => 2601}/scanners/best-practices.md | 0 .../{1.0 => 2601}/scanners/overview.md | 0 kb_allowlist.json | 2 +- sidebars/accessanalyzer/{1.0.js => 2601.js} | 0 src/config/products.js | 6 +- 69 files changed, 73 insertions(+), 12 deletions(-) rename docs/accessanalyzer/{1.0 => 2601}/configurations/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/configurations/configuration-node/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/configurations/configuration-node/application-settings.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/configurations/configuration-node/logs.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/configurations/configuration-node/notifications.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/configurations/configuration-node/scan-executions.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/configurations/configuration-node/scans.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/configurations/configuration-node/sensitive-data/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/configurations/configuration-node/sensitive-data/mip-labeling.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/configurations/configuration-node/sensitive-data/overview.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/configurations/configuration-node/service-accounts.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/configurations/configuration-node/source-groups.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/configurations/configuration-node/users.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/connectors/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/connectors/activedirectory.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/connectors/entra-id/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/connectors/entra-id/app-registration-secret.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/connectors/entra-id/entra-requirements.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/connectors/entra-id/overview.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/connectors/file-servers/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/connectors/file-servers/celerra.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/connectors/file-servers/cifs.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/connectors/file-servers/netapp.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/connectors/file-servers/unity.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/connectors/file-servers/vnx.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/connectors/sharepoint-online/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/connectors/sharepoint-online/azure-permissions.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/connectors/sharepoint-online/tenant-certificate-config.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/dashboards-reports/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/dashboards-reports/active-directory-dashboard/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/dashboards-reports/active-directory-dashboard/overview.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/dashboards-reports/data-security-dashboard/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/dashboards-reports/data-security-dashboard/activity.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/dashboards-reports/data-security-dashboard/overview.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/dashboards-reports/how-to-analyze-the-data.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/dashboards-reports/my-reports.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/gettingstarted/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/gettingstarted/active-directory-sync/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/gettingstarted/active-directory-sync/active-directory.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/gettingstarted/activity-data/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/gettingstarted/activity-data/file-server-activity.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/gettingstarted/activity-monitor-integration/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/gettingstarted/activity-monitor-integration/overview.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/gettingstarted/entra-id-sync/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/gettingstarted/entra-id-sync/entra-id.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/gettingstarted/file-server-scans/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/gettingstarted/file-server-scans/file-server.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/gettingstarted/first-service-account.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/gettingstarted/sharepoint-online-scan/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/gettingstarted/sharepoint-online-scan/sharepoint-online.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/gettingstarted/source-group-wizard.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/index.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/install/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/install/postinstall.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/install/quickinstall.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/install/security.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/install/system/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/install/system/kubernetes.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/install/system/network.md (66%) rename docs/accessanalyzer/{1.0 => 2601}/install/system/requirements.md (75%) rename docs/accessanalyzer/{1.0 => 2601}/install/uninstall.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/overview/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/overview/keyconcepts.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/scanners/_category_.json (100%) rename docs/accessanalyzer/{1.0 => 2601}/scanners/best-practices.md (100%) rename docs/accessanalyzer/{1.0 => 2601}/scanners/overview.md (100%) rename sidebars/accessanalyzer/{1.0.js => 2601.js} (100%) diff --git a/docs/accessanalyzer/1.0/configurations/_category_.json b/docs/accessanalyzer/2601/configurations/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/configurations/_category_.json rename to docs/accessanalyzer/2601/configurations/_category_.json diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/_category_.json b/docs/accessanalyzer/2601/configurations/configuration-node/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/configurations/configuration-node/_category_.json rename to docs/accessanalyzer/2601/configurations/configuration-node/_category_.json diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/application-settings.md b/docs/accessanalyzer/2601/configurations/configuration-node/application-settings.md similarity index 100% rename from docs/accessanalyzer/1.0/configurations/configuration-node/application-settings.md rename to docs/accessanalyzer/2601/configurations/configuration-node/application-settings.md diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/logs.md b/docs/accessanalyzer/2601/configurations/configuration-node/logs.md similarity index 100% rename from docs/accessanalyzer/1.0/configurations/configuration-node/logs.md rename to docs/accessanalyzer/2601/configurations/configuration-node/logs.md diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/notifications.md b/docs/accessanalyzer/2601/configurations/configuration-node/notifications.md similarity index 100% rename from docs/accessanalyzer/1.0/configurations/configuration-node/notifications.md rename to docs/accessanalyzer/2601/configurations/configuration-node/notifications.md diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/scan-executions.md b/docs/accessanalyzer/2601/configurations/configuration-node/scan-executions.md similarity index 100% rename from docs/accessanalyzer/1.0/configurations/configuration-node/scan-executions.md rename to docs/accessanalyzer/2601/configurations/configuration-node/scan-executions.md diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/scans.md b/docs/accessanalyzer/2601/configurations/configuration-node/scans.md similarity index 100% rename from docs/accessanalyzer/1.0/configurations/configuration-node/scans.md rename to docs/accessanalyzer/2601/configurations/configuration-node/scans.md diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data/_category_.json b/docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data/_category_.json rename to docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/_category_.json diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data/mip-labeling.md b/docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/mip-labeling.md similarity index 100% rename from docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data/mip-labeling.md rename to docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/mip-labeling.md diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data/overview.md b/docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/overview.md similarity index 100% rename from docs/accessanalyzer/1.0/configurations/configuration-node/sensitive-data/overview.md rename to docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/overview.md diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/service-accounts.md b/docs/accessanalyzer/2601/configurations/configuration-node/service-accounts.md similarity index 100% rename from docs/accessanalyzer/1.0/configurations/configuration-node/service-accounts.md rename to docs/accessanalyzer/2601/configurations/configuration-node/service-accounts.md diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/source-groups.md b/docs/accessanalyzer/2601/configurations/configuration-node/source-groups.md similarity index 100% rename from docs/accessanalyzer/1.0/configurations/configuration-node/source-groups.md rename to docs/accessanalyzer/2601/configurations/configuration-node/source-groups.md diff --git a/docs/accessanalyzer/1.0/configurations/configuration-node/users.md b/docs/accessanalyzer/2601/configurations/configuration-node/users.md similarity index 100% rename from docs/accessanalyzer/1.0/configurations/configuration-node/users.md rename to docs/accessanalyzer/2601/configurations/configuration-node/users.md diff --git a/docs/accessanalyzer/1.0/connectors/_category_.json b/docs/accessanalyzer/2601/connectors/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/connectors/_category_.json rename to docs/accessanalyzer/2601/connectors/_category_.json diff --git a/docs/accessanalyzer/1.0/connectors/activedirectory.md b/docs/accessanalyzer/2601/connectors/activedirectory.md similarity index 100% rename from docs/accessanalyzer/1.0/connectors/activedirectory.md rename to docs/accessanalyzer/2601/connectors/activedirectory.md diff --git a/docs/accessanalyzer/1.0/connectors/entra-id/_category_.json b/docs/accessanalyzer/2601/connectors/entra-id/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/connectors/entra-id/_category_.json rename to docs/accessanalyzer/2601/connectors/entra-id/_category_.json diff --git a/docs/accessanalyzer/1.0/connectors/entra-id/app-registration-secret.md b/docs/accessanalyzer/2601/connectors/entra-id/app-registration-secret.md similarity index 100% rename from docs/accessanalyzer/1.0/connectors/entra-id/app-registration-secret.md rename to docs/accessanalyzer/2601/connectors/entra-id/app-registration-secret.md diff --git a/docs/accessanalyzer/1.0/connectors/entra-id/entra-requirements.md b/docs/accessanalyzer/2601/connectors/entra-id/entra-requirements.md similarity index 100% rename from docs/accessanalyzer/1.0/connectors/entra-id/entra-requirements.md rename to docs/accessanalyzer/2601/connectors/entra-id/entra-requirements.md diff --git a/docs/accessanalyzer/1.0/connectors/entra-id/overview.md b/docs/accessanalyzer/2601/connectors/entra-id/overview.md similarity index 100% rename from docs/accessanalyzer/1.0/connectors/entra-id/overview.md rename to docs/accessanalyzer/2601/connectors/entra-id/overview.md diff --git a/docs/accessanalyzer/1.0/connectors/file-servers/_category_.json b/docs/accessanalyzer/2601/connectors/file-servers/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/connectors/file-servers/_category_.json rename to docs/accessanalyzer/2601/connectors/file-servers/_category_.json diff --git a/docs/accessanalyzer/1.0/connectors/file-servers/celerra.md b/docs/accessanalyzer/2601/connectors/file-servers/celerra.md similarity index 100% rename from docs/accessanalyzer/1.0/connectors/file-servers/celerra.md rename to docs/accessanalyzer/2601/connectors/file-servers/celerra.md diff --git a/docs/accessanalyzer/1.0/connectors/file-servers/cifs.md b/docs/accessanalyzer/2601/connectors/file-servers/cifs.md similarity index 100% rename from docs/accessanalyzer/1.0/connectors/file-servers/cifs.md rename to docs/accessanalyzer/2601/connectors/file-servers/cifs.md diff --git a/docs/accessanalyzer/1.0/connectors/file-servers/netapp.md b/docs/accessanalyzer/2601/connectors/file-servers/netapp.md similarity index 100% rename from docs/accessanalyzer/1.0/connectors/file-servers/netapp.md rename to docs/accessanalyzer/2601/connectors/file-servers/netapp.md diff --git a/docs/accessanalyzer/1.0/connectors/file-servers/unity.md b/docs/accessanalyzer/2601/connectors/file-servers/unity.md similarity index 100% rename from docs/accessanalyzer/1.0/connectors/file-servers/unity.md rename to docs/accessanalyzer/2601/connectors/file-servers/unity.md diff --git a/docs/accessanalyzer/1.0/connectors/file-servers/vnx.md b/docs/accessanalyzer/2601/connectors/file-servers/vnx.md similarity index 100% rename from docs/accessanalyzer/1.0/connectors/file-servers/vnx.md rename to docs/accessanalyzer/2601/connectors/file-servers/vnx.md diff --git a/docs/accessanalyzer/1.0/connectors/sharepoint-online/_category_.json b/docs/accessanalyzer/2601/connectors/sharepoint-online/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/connectors/sharepoint-online/_category_.json rename to docs/accessanalyzer/2601/connectors/sharepoint-online/_category_.json diff --git a/docs/accessanalyzer/1.0/connectors/sharepoint-online/azure-permissions.md b/docs/accessanalyzer/2601/connectors/sharepoint-online/azure-permissions.md similarity index 100% rename from docs/accessanalyzer/1.0/connectors/sharepoint-online/azure-permissions.md rename to docs/accessanalyzer/2601/connectors/sharepoint-online/azure-permissions.md diff --git a/docs/accessanalyzer/1.0/connectors/sharepoint-online/tenant-certificate-config.md b/docs/accessanalyzer/2601/connectors/sharepoint-online/tenant-certificate-config.md similarity index 100% rename from docs/accessanalyzer/1.0/connectors/sharepoint-online/tenant-certificate-config.md rename to docs/accessanalyzer/2601/connectors/sharepoint-online/tenant-certificate-config.md diff --git a/docs/accessanalyzer/1.0/dashboards-reports/_category_.json b/docs/accessanalyzer/2601/dashboards-reports/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/dashboards-reports/_category_.json rename to docs/accessanalyzer/2601/dashboards-reports/_category_.json diff --git a/docs/accessanalyzer/1.0/dashboards-reports/active-directory-dashboard/_category_.json b/docs/accessanalyzer/2601/dashboards-reports/active-directory-dashboard/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/dashboards-reports/active-directory-dashboard/_category_.json rename to docs/accessanalyzer/2601/dashboards-reports/active-directory-dashboard/_category_.json diff --git a/docs/accessanalyzer/1.0/dashboards-reports/active-directory-dashboard/overview.md b/docs/accessanalyzer/2601/dashboards-reports/active-directory-dashboard/overview.md similarity index 100% rename from docs/accessanalyzer/1.0/dashboards-reports/active-directory-dashboard/overview.md rename to docs/accessanalyzer/2601/dashboards-reports/active-directory-dashboard/overview.md diff --git a/docs/accessanalyzer/1.0/dashboards-reports/data-security-dashboard/_category_.json b/docs/accessanalyzer/2601/dashboards-reports/data-security-dashboard/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/dashboards-reports/data-security-dashboard/_category_.json rename to docs/accessanalyzer/2601/dashboards-reports/data-security-dashboard/_category_.json diff --git a/docs/accessanalyzer/1.0/dashboards-reports/data-security-dashboard/activity.md b/docs/accessanalyzer/2601/dashboards-reports/data-security-dashboard/activity.md similarity index 100% rename from docs/accessanalyzer/1.0/dashboards-reports/data-security-dashboard/activity.md rename to docs/accessanalyzer/2601/dashboards-reports/data-security-dashboard/activity.md diff --git a/docs/accessanalyzer/1.0/dashboards-reports/data-security-dashboard/overview.md b/docs/accessanalyzer/2601/dashboards-reports/data-security-dashboard/overview.md similarity index 100% rename from docs/accessanalyzer/1.0/dashboards-reports/data-security-dashboard/overview.md rename to docs/accessanalyzer/2601/dashboards-reports/data-security-dashboard/overview.md diff --git a/docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-the-data.md b/docs/accessanalyzer/2601/dashboards-reports/how-to-analyze-the-data.md similarity index 100% rename from docs/accessanalyzer/1.0/dashboards-reports/how-to-analyze-the-data.md rename to docs/accessanalyzer/2601/dashboards-reports/how-to-analyze-the-data.md diff --git a/docs/accessanalyzer/1.0/dashboards-reports/my-reports.md b/docs/accessanalyzer/2601/dashboards-reports/my-reports.md similarity index 100% rename from docs/accessanalyzer/1.0/dashboards-reports/my-reports.md rename to docs/accessanalyzer/2601/dashboards-reports/my-reports.md diff --git a/docs/accessanalyzer/1.0/gettingstarted/_category_.json b/docs/accessanalyzer/2601/gettingstarted/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/gettingstarted/_category_.json rename to docs/accessanalyzer/2601/gettingstarted/_category_.json diff --git a/docs/accessanalyzer/1.0/gettingstarted/active-directory-sync/_category_.json b/docs/accessanalyzer/2601/gettingstarted/active-directory-sync/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/gettingstarted/active-directory-sync/_category_.json rename to docs/accessanalyzer/2601/gettingstarted/active-directory-sync/_category_.json diff --git a/docs/accessanalyzer/1.0/gettingstarted/active-directory-sync/active-directory.md b/docs/accessanalyzer/2601/gettingstarted/active-directory-sync/active-directory.md similarity index 100% rename from docs/accessanalyzer/1.0/gettingstarted/active-directory-sync/active-directory.md rename to docs/accessanalyzer/2601/gettingstarted/active-directory-sync/active-directory.md diff --git a/docs/accessanalyzer/1.0/gettingstarted/activity-data/_category_.json b/docs/accessanalyzer/2601/gettingstarted/activity-data/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/gettingstarted/activity-data/_category_.json rename to docs/accessanalyzer/2601/gettingstarted/activity-data/_category_.json diff --git a/docs/accessanalyzer/1.0/gettingstarted/activity-data/file-server-activity.md b/docs/accessanalyzer/2601/gettingstarted/activity-data/file-server-activity.md similarity index 100% rename from docs/accessanalyzer/1.0/gettingstarted/activity-data/file-server-activity.md rename to docs/accessanalyzer/2601/gettingstarted/activity-data/file-server-activity.md diff --git a/docs/accessanalyzer/1.0/gettingstarted/activity-monitor-integration/_category_.json b/docs/accessanalyzer/2601/gettingstarted/activity-monitor-integration/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/gettingstarted/activity-monitor-integration/_category_.json rename to docs/accessanalyzer/2601/gettingstarted/activity-monitor-integration/_category_.json diff --git a/docs/accessanalyzer/1.0/gettingstarted/activity-monitor-integration/overview.md b/docs/accessanalyzer/2601/gettingstarted/activity-monitor-integration/overview.md similarity index 100% rename from docs/accessanalyzer/1.0/gettingstarted/activity-monitor-integration/overview.md rename to docs/accessanalyzer/2601/gettingstarted/activity-monitor-integration/overview.md diff --git a/docs/accessanalyzer/1.0/gettingstarted/entra-id-sync/_category_.json b/docs/accessanalyzer/2601/gettingstarted/entra-id-sync/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/gettingstarted/entra-id-sync/_category_.json rename to docs/accessanalyzer/2601/gettingstarted/entra-id-sync/_category_.json diff --git a/docs/accessanalyzer/1.0/gettingstarted/entra-id-sync/entra-id.md b/docs/accessanalyzer/2601/gettingstarted/entra-id-sync/entra-id.md similarity index 100% rename from docs/accessanalyzer/1.0/gettingstarted/entra-id-sync/entra-id.md rename to docs/accessanalyzer/2601/gettingstarted/entra-id-sync/entra-id.md diff --git a/docs/accessanalyzer/1.0/gettingstarted/file-server-scans/_category_.json b/docs/accessanalyzer/2601/gettingstarted/file-server-scans/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/gettingstarted/file-server-scans/_category_.json rename to docs/accessanalyzer/2601/gettingstarted/file-server-scans/_category_.json diff --git a/docs/accessanalyzer/1.0/gettingstarted/file-server-scans/file-server.md b/docs/accessanalyzer/2601/gettingstarted/file-server-scans/file-server.md similarity index 100% rename from docs/accessanalyzer/1.0/gettingstarted/file-server-scans/file-server.md rename to docs/accessanalyzer/2601/gettingstarted/file-server-scans/file-server.md diff --git a/docs/accessanalyzer/1.0/gettingstarted/first-service-account.md b/docs/accessanalyzer/2601/gettingstarted/first-service-account.md similarity index 100% rename from docs/accessanalyzer/1.0/gettingstarted/first-service-account.md rename to docs/accessanalyzer/2601/gettingstarted/first-service-account.md diff --git a/docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan/_category_.json b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online-scan/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan/_category_.json rename to docs/accessanalyzer/2601/gettingstarted/sharepoint-online-scan/_category_.json diff --git a/docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan/sharepoint-online.md b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online-scan/sharepoint-online.md similarity index 100% rename from docs/accessanalyzer/1.0/gettingstarted/sharepoint-online-scan/sharepoint-online.md rename to docs/accessanalyzer/2601/gettingstarted/sharepoint-online-scan/sharepoint-online.md diff --git a/docs/accessanalyzer/1.0/gettingstarted/source-group-wizard.md b/docs/accessanalyzer/2601/gettingstarted/source-group-wizard.md similarity index 100% rename from docs/accessanalyzer/1.0/gettingstarted/source-group-wizard.md rename to docs/accessanalyzer/2601/gettingstarted/source-group-wizard.md diff --git a/docs/accessanalyzer/1.0/index.md b/docs/accessanalyzer/2601/index.md similarity index 100% rename from docs/accessanalyzer/1.0/index.md rename to docs/accessanalyzer/2601/index.md diff --git a/docs/accessanalyzer/1.0/install/_category_.json b/docs/accessanalyzer/2601/install/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/install/_category_.json rename to docs/accessanalyzer/2601/install/_category_.json diff --git a/docs/accessanalyzer/1.0/install/postinstall.md b/docs/accessanalyzer/2601/install/postinstall.md similarity index 100% rename from docs/accessanalyzer/1.0/install/postinstall.md rename to docs/accessanalyzer/2601/install/postinstall.md diff --git a/docs/accessanalyzer/1.0/install/quickinstall.md b/docs/accessanalyzer/2601/install/quickinstall.md similarity index 100% rename from docs/accessanalyzer/1.0/install/quickinstall.md rename to docs/accessanalyzer/2601/install/quickinstall.md diff --git a/docs/accessanalyzer/1.0/install/security.md b/docs/accessanalyzer/2601/install/security.md similarity index 100% rename from docs/accessanalyzer/1.0/install/security.md rename to docs/accessanalyzer/2601/install/security.md diff --git a/docs/accessanalyzer/1.0/install/system/_category_.json b/docs/accessanalyzer/2601/install/system/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/install/system/_category_.json rename to docs/accessanalyzer/2601/install/system/_category_.json diff --git a/docs/accessanalyzer/1.0/install/system/kubernetes.md b/docs/accessanalyzer/2601/install/system/kubernetes.md similarity index 100% rename from docs/accessanalyzer/1.0/install/system/kubernetes.md rename to docs/accessanalyzer/2601/install/system/kubernetes.md diff --git a/docs/accessanalyzer/1.0/install/system/network.md b/docs/accessanalyzer/2601/install/system/network.md similarity index 66% rename from docs/accessanalyzer/1.0/install/system/network.md rename to docs/accessanalyzer/2601/install/system/network.md index 8643ce201b..435e186cc3 100644 --- a/docs/accessanalyzer/1.0/install/system/network.md +++ b/docs/accessanalyzer/2601/install/system/network.md @@ -74,9 +74,68 @@ If outbound traffic is routed through a proxy, set the following environment var ```bash export HTTP_PROXY="http://:" export HTTPS_PROXY="http://:" -export NO_PROXY="localhost,127.0.0.1,10.0.0.0/8" +export NO_PROXY="localhost,127.0.0.1,.svc,.cluster.local,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16" ``` +## Antivirus Exclusions + +If an endpoint detection or antivirus product is running on the Access Analyzer host, configure exclusions for the following paths before installation. The installer's preflight checks detect common products (CrowdStrike Falcon, SentinelOne, Sophos, and others) and will prompt you to confirm exclusions are in place. + +| Path | Reason | +| --- | --- | +| `/var/lib/rancher/` | K3s runtime data | +| `/var/lib/containerd/` | Container image layers | +| `/run/k3s/` | K3s socket and runtime files | +| `/usr/local/bin/k3s` | K3s binary | + +:::note +Setting `SKIP_AV_CHECK=true` before running the installer bypasses the antivirus detection prompt, but does not configure exclusions automatically. Configure exclusions manually before running the installer. +::: + ## Firewall Configuration -See [Network Configuration](/docs/accessanalyzer/1_0/install/network) for firewall rule examples for Azure, AWS, and on-premises environments. +Allow outbound HTTPS (port 443) to all endpoints listed in the [Outbound Endpoints](#outbound-endpoints-internet) table above. The examples below show how to configure this on common platforms. + +### Azure (NSG Rule) + +```bash +az network nsg rule create \ + --resource-group \ + --nsg-name \ + --name AllowOutboundHTTPS \ + --priority 100 \ + --direction Outbound \ + --access Allow \ + --protocol Tcp \ + --destination-port-ranges 443 +``` + +### AWS (EC2 Security Group) + +```bash +aws ec2 authorize-security-group-egress \ + --group-id \ + --protocol tcp \ + --port 443 \ + --cidr 0.0.0.0/0 +``` + +### On-Premises (ufw) + +```bash +sudo ufw allow out 443/tcp +sudo ufw reload +``` + +### Verify Connectivity + +After configuring firewall rules, verify that the required endpoints are reachable from the Access Analyzer server: + +```bash +curl -I https://oci.pkg.keygen.sh +curl -I https://ghcr.io +curl -I https://registry-1.docker.io +curl -I https://get.k3s.io +``` + +All commands should return an HTTP response (2xx or 3xx). A connection timeout or refusal indicates a firewall rule is blocking the endpoint. diff --git a/docs/accessanalyzer/1.0/install/system/requirements.md b/docs/accessanalyzer/2601/install/system/requirements.md similarity index 75% rename from docs/accessanalyzer/1.0/install/system/requirements.md rename to docs/accessanalyzer/2601/install/system/requirements.md index 885dc0fdaf..20dfd2437e 100644 --- a/docs/accessanalyzer/1.0/install/system/requirements.md +++ b/docs/accessanalyzer/2601/install/system/requirements.md @@ -10,14 +10,16 @@ Access Analyzer is deployed on a single Linux virtual machine. The installer run ## Deployment Sizing -| Size | CPU | Memory | Disk | Use Case | -| --- | --- | --- | --- | --- | -| **Small** | 2 vCPUs (4 recommended) | 8 GB (16 GB recommended) | 20 GB free (50 GB recommended) | Evaluation and small environments | -| **Medium** | 8 vCPUs | 32 GB | 100 GB SSD | Mid-size environments | -| **Large** | 16 vCPUs | 64 GB | 500 GB SSD | Large enterprise environments | +Use the **Minimum** specifications for evaluation and lab deployments. Use the **Production Recommended** specifications for customer-facing or enterprise deployments. The installer enforces the minimum thresholds — preflight checks will fail if the system falls below them. + +| Size | Min CPU | Min Memory | Min Disk | Prod CPU | Prod Memory | Prod Disk | Typical Environment | +| --- | --- | --- | --- | --- | --- | --- | --- | +| **Small** | 2 vCPUs | 8 GB | 20 GB free | 8 cores | 32 GB | 1 TB SSD | Evaluation, pilots, up to ~1,000 assets | +| **Medium** | 4 vCPUs | 16 GB | 50 GB free | 16 cores | 64 GB | 1 TB SSD | Up to ~5,000 assets | +| **Large** | 8 vCPUs | 32 GB | 100 GB free | 32 cores | 128 GB | 1 TB SSD | 5,000+ assets / enterprise | :::note -The `--size` flag scales memory requirements by the specified multiplier. For example, `--size 2` doubles the minimum and recommended memory thresholds. See [Environment Variables](/docs/accessanalyzer/1_0/install/environmentvariables) for details. +The `--size` flag scales memory thresholds by the specified multiplier. For example, `--size 2` doubles the minimum and recommended memory requirements enforced by the preflight checks. ::: ## Disk Space Requirements diff --git a/docs/accessanalyzer/1.0/install/uninstall.md b/docs/accessanalyzer/2601/install/uninstall.md similarity index 100% rename from docs/accessanalyzer/1.0/install/uninstall.md rename to docs/accessanalyzer/2601/install/uninstall.md diff --git a/docs/accessanalyzer/1.0/overview/_category_.json b/docs/accessanalyzer/2601/overview/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/overview/_category_.json rename to docs/accessanalyzer/2601/overview/_category_.json diff --git a/docs/accessanalyzer/1.0/overview/keyconcepts.md b/docs/accessanalyzer/2601/overview/keyconcepts.md similarity index 100% rename from docs/accessanalyzer/1.0/overview/keyconcepts.md rename to docs/accessanalyzer/2601/overview/keyconcepts.md diff --git a/docs/accessanalyzer/1.0/scanners/_category_.json b/docs/accessanalyzer/2601/scanners/_category_.json similarity index 100% rename from docs/accessanalyzer/1.0/scanners/_category_.json rename to docs/accessanalyzer/2601/scanners/_category_.json diff --git a/docs/accessanalyzer/1.0/scanners/best-practices.md b/docs/accessanalyzer/2601/scanners/best-practices.md similarity index 100% rename from docs/accessanalyzer/1.0/scanners/best-practices.md rename to docs/accessanalyzer/2601/scanners/best-practices.md diff --git a/docs/accessanalyzer/1.0/scanners/overview.md b/docs/accessanalyzer/2601/scanners/overview.md similarity index 100% rename from docs/accessanalyzer/1.0/scanners/overview.md rename to docs/accessanalyzer/2601/scanners/overview.md diff --git a/kb_allowlist.json b/kb_allowlist.json index b39f8edc6e..322f46e175 100644 --- a/kb_allowlist.json +++ b/kb_allowlist.json @@ -3,7 +3,7 @@ "current" ], "accessanalyzer": [ - "1.0", + "2601", "11.6", "12.0" ], diff --git a/sidebars/accessanalyzer/1.0.js b/sidebars/accessanalyzer/2601.js similarity index 100% rename from sidebars/accessanalyzer/1.0.js rename to sidebars/accessanalyzer/2601.js diff --git a/src/config/products.js b/src/config/products.js index a1e65be057..6160797ec9 100644 --- a/src/config/products.js +++ b/src/config/products.js @@ -61,10 +61,10 @@ export const PRODUCTS = [ icon: '', versions: [ { - version: '1.0', - label: '1.0', + version: '2601', + label: '2601', isLatest: false, - sidebarFile: './sidebars/accessanalyzer/1.0.js', + sidebarFile: './sidebars/accessanalyzer/2601.js', }, { version: '12.0', From d79ccadc12d3107cbb8829a71dc6531ba8f94150 Mon Sep 17 00:00:00 2001 From: carlos-mejia_nwx Date: Wed, 8 Apr 2026 00:08:33 -0400 Subject: [PATCH 20/62] =?UTF-8?q?AA26:=20Remove=20Unity,=20Celerra,=20and?= =?UTF-8?q?=20VNX=20connector=20pages=20=E2=80=94=20not=20supported=20at?= =?UTF-8?q?=20GA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- .../2601/connectors/file-servers/celerra.md | 9 --------- .../accessanalyzer/2601/connectors/file-servers/unity.md | 9 --------- docs/accessanalyzer/2601/connectors/file-servers/vnx.md | 9 --------- 3 files changed, 27 deletions(-) delete mode 100644 docs/accessanalyzer/2601/connectors/file-servers/celerra.md delete mode 100644 docs/accessanalyzer/2601/connectors/file-servers/unity.md delete mode 100644 docs/accessanalyzer/2601/connectors/file-servers/vnx.md diff --git a/docs/accessanalyzer/2601/connectors/file-servers/celerra.md b/docs/accessanalyzer/2601/connectors/file-servers/celerra.md deleted file mode 100644 index e562473a05..0000000000 --- a/docs/accessanalyzer/2601/connectors/file-servers/celerra.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Celerra" -description: "Connector requirements for Dell Celerra file servers" -sidebar_position: 30 ---- - -# Celerra - -*Content coming soon.* diff --git a/docs/accessanalyzer/2601/connectors/file-servers/unity.md b/docs/accessanalyzer/2601/connectors/file-servers/unity.md deleted file mode 100644 index 55cc8ba73a..0000000000 --- a/docs/accessanalyzer/2601/connectors/file-servers/unity.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Unity" -description: "Connector requirements for Dell Unity file servers" -sidebar_position: 20 ---- - -# Unity - -*Content coming soon.* diff --git a/docs/accessanalyzer/2601/connectors/file-servers/vnx.md b/docs/accessanalyzer/2601/connectors/file-servers/vnx.md deleted file mode 100644 index cbaba1af7a..0000000000 --- a/docs/accessanalyzer/2601/connectors/file-servers/vnx.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "VNX" -description: "Connector requirements for Dell VNX file servers" -sidebar_position: 40 ---- - -# VNX - -*Content coming soon.* From 2e65d5ece31f9b9fb84419366e4eec8444baab22 Mon Sep 17 00:00:00 2001 From: Farrah Gamboa Date: Thu, 9 Apr 2026 14:06:44 -0700 Subject: [PATCH 21/62] AA26: Add quick start guides, schema references, reports pages, and overview MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add full quick start guides for Active Directory, File Servers, Entra ID, and SharePoint Online — each with a scanning overview, scanning options, set-up walkthrough, schema reference (where applicable), and reports page - Add product overview and architecture overview with Mermaid diagram - Restructure configurations: flatten configuration-node hierarchy, nest Scanners under Source Groups, add service accounts subsection - Add SharePoint Online connector overview page - Remove replaced stubs: activity-data, activity-monitor-integration, old getting-started placeholders, top-level scanners section - Update inbound links to reflect new scanner path under source-groups Generated with AI Co-Authored-By: Claude Code --- .../2601/configurations/_category_.json | 2 +- .../application-settings.md | 0 .../sensitive-data/_category_.json | 6 - .../sensitive-data/mip-labeling.md | 9 - .../sensitive-data/overview.md | 9 - .../configuration-node/service-accounts.md | 9 - .../{configuration-node => }/logs.md | 0 .../{configuration-node => }/notifications.md | 0 .../2601/configurations/sensitive-data.md | 11 + .../service-accounts/_category_.json | 6 + .../service-accounts/entra-id.md | 19 ++ .../service-accounts/overview.md | 29 ++ .../service-accounts/sharepoint-online.md | 24 ++ .../service-accounts/username-password.md | 29 ++ .../_category_.json | 2 +- .../scan-executions.md | 2 +- .../source-groups}/scanners/_category_.json | 0 .../source-groups}/scanners/best-practices.md | 0 .../source-groups}/scanners/overview.md | 0 .../scans.md | 2 +- .../source-groups.md | 2 +- .../{configuration-node => }/users.md | 0 .../2601/connectors/activedirectory.md | 14 + .../2601/connectors/file-servers/cifs.md | 2 +- .../sharepoint-online/_category_.json | 6 +- .../connectors/sharepoint-online/overview.md | 37 +++ .../active-directory-sync/active-directory.md | 9 - .../_category_.json | 2 +- .../active-directory/active-directory.md | 32 ++ .../active-directory/reports.md | 15 + .../active-directory/scanning-options.md | 11 + .../active-directory/schema-reference.md | 273 ++++++++++++++++++ .../active-directory/set-up-source-group.md | 57 ++++ .../activity-data/_category_.json | 6 - .../activity-data/file-server-activity.md | 9 - .../_category_.json | 6 - .../activity-monitor-integration/overview.md | 9 - .../gettingstarted/entra-id-sync/entra-id.md | 9 - .../_category_.json | 2 +- .../2601/gettingstarted/entra-id/entra-id.md | 34 +++ .../entra-id/scanning-options.md | 11 + .../entra-id/set-up-source-group.md | 45 +++ .../file-server-scans/file-server.md | 9 - .../_category_.json | 2 +- .../file-servers/file-servers.md | 31 ++ .../gettingstarted/file-servers/reports.md | 31 ++ .../file-servers/scanning-options.md | 28 ++ .../file-servers/schema-reference.md | 201 +++++++++++++ .../file-servers/set-up-source-group.md | 62 ++++ .../gettingstarted/first-service-account.md | 9 - .../sharepoint-online.md | 9 - .../_category_.json | 2 +- .../sharepoint-online/reports.md | 17 ++ .../sharepoint-online/scanning-options.md | 17 ++ .../sharepoint-online/schema-reference.md | 166 +++++++++++ .../sharepoint-online/set-up-source-group.md | 49 ++++ .../sharepoint-online/sharepoint-online.md | 33 +++ .../gettingstarted/source-group-wizard.md | 9 - docs/accessanalyzer/2601/overview/overview.md | 100 +++++++ kb_allowlist.json | 4 +- 60 files changed, 1399 insertions(+), 130 deletions(-) rename docs/accessanalyzer/2601/configurations/{configuration-node => }/application-settings.md (100%) delete mode 100644 docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/_category_.json delete mode 100644 docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/mip-labeling.md delete mode 100644 docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/overview.md delete mode 100644 docs/accessanalyzer/2601/configurations/configuration-node/service-accounts.md rename docs/accessanalyzer/2601/configurations/{configuration-node => }/logs.md (100%) rename docs/accessanalyzer/2601/configurations/{configuration-node => }/notifications.md (100%) create mode 100644 docs/accessanalyzer/2601/configurations/sensitive-data.md create mode 100644 docs/accessanalyzer/2601/configurations/service-accounts/_category_.json create mode 100644 docs/accessanalyzer/2601/configurations/service-accounts/entra-id.md create mode 100644 docs/accessanalyzer/2601/configurations/service-accounts/overview.md create mode 100644 docs/accessanalyzer/2601/configurations/service-accounts/sharepoint-online.md create mode 100644 docs/accessanalyzer/2601/configurations/service-accounts/username-password.md rename docs/accessanalyzer/2601/configurations/{configuration-node => source-groups}/_category_.json (69%) rename docs/accessanalyzer/2601/configurations/{configuration-node => source-groups}/scan-executions.md (87%) rename docs/accessanalyzer/2601/{ => configurations/source-groups}/scanners/_category_.json (100%) rename docs/accessanalyzer/2601/{ => configurations/source-groups}/scanners/best-practices.md (100%) rename docs/accessanalyzer/2601/{ => configurations/source-groups}/scanners/overview.md (100%) rename docs/accessanalyzer/2601/configurations/{configuration-node => source-groups}/scans.md (84%) rename docs/accessanalyzer/2601/configurations/{configuration-node => source-groups}/source-groups.md (86%) rename docs/accessanalyzer/2601/configurations/{configuration-node => }/users.md (100%) create mode 100644 docs/accessanalyzer/2601/connectors/sharepoint-online/overview.md delete mode 100644 docs/accessanalyzer/2601/gettingstarted/active-directory-sync/active-directory.md rename docs/accessanalyzer/2601/gettingstarted/{active-directory-sync => active-directory}/_category_.json (61%) create mode 100644 docs/accessanalyzer/2601/gettingstarted/active-directory/active-directory.md create mode 100644 docs/accessanalyzer/2601/gettingstarted/active-directory/reports.md create mode 100644 docs/accessanalyzer/2601/gettingstarted/active-directory/scanning-options.md create mode 100644 docs/accessanalyzer/2601/gettingstarted/active-directory/schema-reference.md create mode 100644 docs/accessanalyzer/2601/gettingstarted/active-directory/set-up-source-group.md delete mode 100644 docs/accessanalyzer/2601/gettingstarted/activity-data/_category_.json delete mode 100644 docs/accessanalyzer/2601/gettingstarted/activity-data/file-server-activity.md delete mode 100644 docs/accessanalyzer/2601/gettingstarted/activity-monitor-integration/_category_.json delete mode 100644 docs/accessanalyzer/2601/gettingstarted/activity-monitor-integration/overview.md delete mode 100644 docs/accessanalyzer/2601/gettingstarted/entra-id-sync/entra-id.md rename docs/accessanalyzer/2601/gettingstarted/{entra-id-sync => entra-id}/_category_.json (67%) create mode 100644 docs/accessanalyzer/2601/gettingstarted/entra-id/entra-id.md create mode 100644 docs/accessanalyzer/2601/gettingstarted/entra-id/scanning-options.md create mode 100644 docs/accessanalyzer/2601/gettingstarted/entra-id/set-up-source-group.md delete mode 100644 docs/accessanalyzer/2601/gettingstarted/file-server-scans/file-server.md rename docs/accessanalyzer/2601/gettingstarted/{file-server-scans => file-servers}/_category_.json (64%) create mode 100644 docs/accessanalyzer/2601/gettingstarted/file-servers/file-servers.md create mode 100644 docs/accessanalyzer/2601/gettingstarted/file-servers/reports.md create mode 100644 docs/accessanalyzer/2601/gettingstarted/file-servers/scanning-options.md create mode 100644 docs/accessanalyzer/2601/gettingstarted/file-servers/schema-reference.md create mode 100644 docs/accessanalyzer/2601/gettingstarted/file-servers/set-up-source-group.md delete mode 100644 docs/accessanalyzer/2601/gettingstarted/first-service-account.md delete mode 100644 docs/accessanalyzer/2601/gettingstarted/sharepoint-online-scan/sharepoint-online.md rename docs/accessanalyzer/2601/gettingstarted/{sharepoint-online-scan => sharepoint-online}/_category_.json (61%) create mode 100644 docs/accessanalyzer/2601/gettingstarted/sharepoint-online/reports.md create mode 100644 docs/accessanalyzer/2601/gettingstarted/sharepoint-online/scanning-options.md create mode 100644 docs/accessanalyzer/2601/gettingstarted/sharepoint-online/schema-reference.md create mode 100644 docs/accessanalyzer/2601/gettingstarted/sharepoint-online/set-up-source-group.md create mode 100644 docs/accessanalyzer/2601/gettingstarted/sharepoint-online/sharepoint-online.md delete mode 100644 docs/accessanalyzer/2601/gettingstarted/source-group-wizard.md create mode 100644 docs/accessanalyzer/2601/overview/overview.md diff --git a/docs/accessanalyzer/2601/configurations/_category_.json b/docs/accessanalyzer/2601/configurations/_category_.json index 76daee8c8e..e493e2c253 100644 --- a/docs/accessanalyzer/2601/configurations/_category_.json +++ b/docs/accessanalyzer/2601/configurations/_category_.json @@ -1,6 +1,6 @@ { "label": "Configuration", - "position": 30, + "position": 16, "collapsed": true, "collapsible": true } diff --git a/docs/accessanalyzer/2601/configurations/configuration-node/application-settings.md b/docs/accessanalyzer/2601/configurations/application-settings.md similarity index 100% rename from docs/accessanalyzer/2601/configurations/configuration-node/application-settings.md rename to docs/accessanalyzer/2601/configurations/application-settings.md diff --git a/docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/_category_.json b/docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/_category_.json deleted file mode 100644 index 7965ccfb43..0000000000 --- a/docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Sensitive Data", - "position": 60, - "collapsed": true, - "collapsible": true -} diff --git a/docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/mip-labeling.md b/docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/mip-labeling.md deleted file mode 100644 index 32bed90184..0000000000 --- a/docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/mip-labeling.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "MIP Labeling" -description: "Microsoft Information Protection labeling and workflow configuration" -sidebar_position: 10 ---- - -# MIP Labeling - -*Content coming soon.* diff --git a/docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/overview.md b/docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/overview.md deleted file mode 100644 index b1535ed51f..0000000000 --- a/docs/accessanalyzer/2601/configurations/configuration-node/sensitive-data/overview.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Sensitive Data" -description: "Managing sensitive data settings in the Configuration node" -sidebar_position: 5 ---- - -# Sensitive Data - -*Content coming soon.* diff --git a/docs/accessanalyzer/2601/configurations/configuration-node/service-accounts.md b/docs/accessanalyzer/2601/configurations/configuration-node/service-accounts.md deleted file mode 100644 index 956d4289c2..0000000000 --- a/docs/accessanalyzer/2601/configurations/configuration-node/service-accounts.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Service Accounts" -description: "Managing service accounts in the Configuration node" -sidebar_position: 10 ---- - -# Service Accounts - -*Content coming soon.* diff --git a/docs/accessanalyzer/2601/configurations/configuration-node/logs.md b/docs/accessanalyzer/2601/configurations/logs.md similarity index 100% rename from docs/accessanalyzer/2601/configurations/configuration-node/logs.md rename to docs/accessanalyzer/2601/configurations/logs.md diff --git a/docs/accessanalyzer/2601/configurations/configuration-node/notifications.md b/docs/accessanalyzer/2601/configurations/notifications.md similarity index 100% rename from docs/accessanalyzer/2601/configurations/configuration-node/notifications.md rename to docs/accessanalyzer/2601/configurations/notifications.md diff --git a/docs/accessanalyzer/2601/configurations/sensitive-data.md b/docs/accessanalyzer/2601/configurations/sensitive-data.md new file mode 100644 index 0000000000..cb72b8ca1f --- /dev/null +++ b/docs/accessanalyzer/2601/configurations/sensitive-data.md @@ -0,0 +1,11 @@ +--- +title: "Sensitive Data" +description: "Configure sensitive data scanning settings in Access Analyzer" +sidebar_position: 30 +--- + +# Sensitive Data + +Sensitive data configuration controls how Access Analyzer identifies and classifies sensitive content during scans. Settings apply globally across all source groups that include sensitive data scanning. + +Configuration options include classification criteria, file type filters, and scanning depth. These settings determine what qualifies as sensitive data in scan results and how it is reported in the dashboards. diff --git a/docs/accessanalyzer/2601/configurations/service-accounts/_category_.json b/docs/accessanalyzer/2601/configurations/service-accounts/_category_.json new file mode 100644 index 0000000000..25ffc0442b --- /dev/null +++ b/docs/accessanalyzer/2601/configurations/service-accounts/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Service Accounts", + "position": 10, + "collapsed": true, + "collapsible": true +} diff --git a/docs/accessanalyzer/2601/configurations/service-accounts/entra-id.md b/docs/accessanalyzer/2601/configurations/service-accounts/entra-id.md new file mode 100644 index 0000000000..e62de9a69e --- /dev/null +++ b/docs/accessanalyzer/2601/configurations/service-accounts/entra-id.md @@ -0,0 +1,19 @@ +--- +title: "Entra ID Service Account" +description: "Client ID and secret service accounts for Entra ID source groups" +sidebar_position: 3 +--- + +# Entra ID Service Account + +Entra ID source groups use the Client ID and Secret credential type to authenticate with Microsoft Entra ID via the Microsoft Graph API. This requires a registered application in your Entra ID tenant with the appropriate API permissions granted. + +## Fields + +| Field | Description | +| --- | --- | +| **Name** | A display name that identifies this service account in Access Analyzer. | +| **Client ID** | The Application (client) ID of your registered Entra ID application. Must be a valid UUID (for example, `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`). Find this in the Azure portal under **Azure Active Directory** > **App registrations** > your app > **Overview**. | +| **Client Secret** | A client secret generated for the registered application. Create one in the Azure portal under your app's **Certificates & secrets**. | + +For steps to register the application and grant the required API permissions, see [Entra ID Requirements](../../connectors/entra-id/overview.md). diff --git a/docs/accessanalyzer/2601/configurations/service-accounts/overview.md b/docs/accessanalyzer/2601/configurations/service-accounts/overview.md new file mode 100644 index 0000000000..d3d151b21e --- /dev/null +++ b/docs/accessanalyzer/2601/configurations/service-accounts/overview.md @@ -0,0 +1,29 @@ +--- +title: "Overview" +description: "How service accounts work in Access Analyzer and which credential type each data source requires" +sidebar_position: 1 +--- + +# Overview + +Service accounts store the credentials Access Analyzer uses to authenticate against data sources during scans. Each data source connector requires a specific credential type, and the source group wizard automatically selects the correct type when you set up a new source group. + +You can create a service account in two ways: + +- **Inline during source group setup** — Click **+** next to the **Service Account** field in the source group wizard. The wizard locks the credential type to match the data source being configured. +- **In advance from Configuration** — Navigate to **Configuration** > **Service Accounts** and click **Add**. Select the credential type that matches your intended data source. + +## Credential Types by Data Source + +| Data Source | Credential Type | +| --- | --- | +| Active Directory | Username and Password | +| File Server | Username and Password | +| Entra ID | Client ID and Secret | +| SharePoint Online | Client ID and Certificate | + +## Editing Service Accounts + +Credential fields — passwords and client secrets — are never pre-populated when you edit an existing service account. You must re-enter them each time you save changes. + +Updating the service account on an existing source group replaces the credentials used for all future scans in that source group. Ensure the replacement account has the required permissions before saving. diff --git a/docs/accessanalyzer/2601/configurations/service-accounts/sharepoint-online.md b/docs/accessanalyzer/2601/configurations/service-accounts/sharepoint-online.md new file mode 100644 index 0000000000..d9db342fe0 --- /dev/null +++ b/docs/accessanalyzer/2601/configurations/service-accounts/sharepoint-online.md @@ -0,0 +1,24 @@ +--- +title: "SharePoint Online Service Account" +description: "Client ID and certificate service accounts for SharePoint Online source groups" +sidebar_position: 4 +--- + +# SharePoint Online Service Account + +SharePoint Online source groups use the Client ID and Certificate credential type to authenticate with SharePoint Online using certificate-based authentication. This requires a registered application in your Entra ID tenant. The certificate is generated by the source group wizard — you don't create or upload it here. + +## Fields + +| Field | Description | +| --- | --- | +| **Name** | A display name that identifies this service account in Access Analyzer. | +| **Client ID** | The Application (client) ID of your registered Entra ID application. Must be a valid UUID (for example, `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`). Find this in the Azure portal under **Azure Active Directory** > **App registrations** > your app > **Overview**. | + +## Certificate + +The certificate is not entered manually. When you set up a SharePoint Online source group, the wizard includes a **Generate and Download Certificate** step that creates the certificate and downloads it to your machine. You then upload the certificate to your registered Entra ID application in the Azure portal before testing the connection. + +If you update the service account on an existing source group, the new account's certificate must be uploaded to the registered app before saving. + +For steps to register the application and upload the certificate, see [SharePoint Online Connector Requirements](../../connectors/sharepoint-online/overview.md). diff --git a/docs/accessanalyzer/2601/configurations/service-accounts/username-password.md b/docs/accessanalyzer/2601/configurations/service-accounts/username-password.md new file mode 100644 index 0000000000..aecba5470d --- /dev/null +++ b/docs/accessanalyzer/2601/configurations/service-accounts/username-password.md @@ -0,0 +1,29 @@ +--- +title: "Username and Password" +description: "Username and password service accounts for Active Directory and file server source groups" +sidebar_position: 2 +--- + +# Username and Password + +The Username and Password credential type is used by Active Directory and file server source groups. Both require a domain account whose credentials Access Analyzer uses to connect and authenticate during scans. + +## Fields + +| Field | Description | +| --- | --- | +| **Name** | A display name that identifies this service account in Access Analyzer. | +| **Username** | The domain user account in `DOMAIN\username` format. | +| **Password** | The password for the domain account. | + +## Active Directory + +Active Directory source groups use the service account to connect to domain controllers over LDAP or LDAPS and read directory objects. The account must have Read access to the Active Directory directory tree. + +For full permission requirements, see [Active Directory Connector Requirements](../../connectors/activedirectory.md). + +## File Server + +File server source groups use the service account to connect to Windows file servers over SMB and enumerate shares, permissions, and file contents. The account must be a member of the same domain as the target file servers. The specific permissions required depend on the scan types you enable — access scanning and sensitive data scanning have different requirements. + +For full permission requirements, see [CIFS / SMB File Share](../../connectors/file-servers/cifs.md). diff --git a/docs/accessanalyzer/2601/configurations/configuration-node/_category_.json b/docs/accessanalyzer/2601/configurations/source-groups/_category_.json similarity index 69% rename from docs/accessanalyzer/2601/configurations/configuration-node/_category_.json rename to docs/accessanalyzer/2601/configurations/source-groups/_category_.json index 70b787ca97..e3bbafe95d 100644 --- a/docs/accessanalyzer/2601/configurations/configuration-node/_category_.json +++ b/docs/accessanalyzer/2601/configurations/source-groups/_category_.json @@ -1,5 +1,5 @@ { - "label": "Settings", + "label": "Source Groups", "position": 20, "collapsed": true, "collapsible": true diff --git a/docs/accessanalyzer/2601/configurations/configuration-node/scan-executions.md b/docs/accessanalyzer/2601/configurations/source-groups/scan-executions.md similarity index 87% rename from docs/accessanalyzer/2601/configurations/configuration-node/scan-executions.md rename to docs/accessanalyzer/2601/configurations/source-groups/scan-executions.md index d2f01e283b..06fdfae6a1 100644 --- a/docs/accessanalyzer/2601/configurations/configuration-node/scan-executions.md +++ b/docs/accessanalyzer/2601/configurations/source-groups/scan-executions.md @@ -1,7 +1,7 @@ --- title: "Scan Executions" description: "Viewing scan execution history in the Configuration node" -sidebar_position: 40 +sidebar_position: 3 --- # Scan Executions diff --git a/docs/accessanalyzer/2601/scanners/_category_.json b/docs/accessanalyzer/2601/configurations/source-groups/scanners/_category_.json similarity index 100% rename from docs/accessanalyzer/2601/scanners/_category_.json rename to docs/accessanalyzer/2601/configurations/source-groups/scanners/_category_.json diff --git a/docs/accessanalyzer/2601/scanners/best-practices.md b/docs/accessanalyzer/2601/configurations/source-groups/scanners/best-practices.md similarity index 100% rename from docs/accessanalyzer/2601/scanners/best-practices.md rename to docs/accessanalyzer/2601/configurations/source-groups/scanners/best-practices.md diff --git a/docs/accessanalyzer/2601/scanners/overview.md b/docs/accessanalyzer/2601/configurations/source-groups/scanners/overview.md similarity index 100% rename from docs/accessanalyzer/2601/scanners/overview.md rename to docs/accessanalyzer/2601/configurations/source-groups/scanners/overview.md diff --git a/docs/accessanalyzer/2601/configurations/configuration-node/scans.md b/docs/accessanalyzer/2601/configurations/source-groups/scans.md similarity index 84% rename from docs/accessanalyzer/2601/configurations/configuration-node/scans.md rename to docs/accessanalyzer/2601/configurations/source-groups/scans.md index 0f21da4b92..cbd6f26304 100644 --- a/docs/accessanalyzer/2601/configurations/configuration-node/scans.md +++ b/docs/accessanalyzer/2601/configurations/source-groups/scans.md @@ -1,7 +1,7 @@ --- title: "Scans" description: "Managing scans in the Configuration node" -sidebar_position: 30 +sidebar_position: 2 --- # Scans diff --git a/docs/accessanalyzer/2601/configurations/configuration-node/source-groups.md b/docs/accessanalyzer/2601/configurations/source-groups/source-groups.md similarity index 86% rename from docs/accessanalyzer/2601/configurations/configuration-node/source-groups.md rename to docs/accessanalyzer/2601/configurations/source-groups/source-groups.md index 0eab251842..1ee2b78421 100644 --- a/docs/accessanalyzer/2601/configurations/configuration-node/source-groups.md +++ b/docs/accessanalyzer/2601/configurations/source-groups/source-groups.md @@ -1,7 +1,7 @@ --- title: "Source Groups" description: "Managing source groups in the Configuration node" -sidebar_position: 20 +sidebar_position: 1 --- # Source Groups diff --git a/docs/accessanalyzer/2601/configurations/configuration-node/users.md b/docs/accessanalyzer/2601/configurations/users.md similarity index 100% rename from docs/accessanalyzer/2601/configurations/configuration-node/users.md rename to docs/accessanalyzer/2601/configurations/users.md diff --git a/docs/accessanalyzer/2601/connectors/activedirectory.md b/docs/accessanalyzer/2601/connectors/activedirectory.md index 6a2949d4f2..916c73f9f5 100644 --- a/docs/accessanalyzer/2601/connectors/activedirectory.md +++ b/docs/accessanalyzer/2601/connectors/activedirectory.md @@ -28,6 +28,8 @@ The following must be installed on each domain controller to be scanned: Use Domain Administrator or Local Administrator privileges when running Access Analyzer against an Active Directory domain controller. ::: +A least privilege model can be configured based on your auditing needs. See the [Least Privilege Model](#least-privilege-model) section for additional information. + ## Port Requirements The following firewall ports are required for the Active Directory connector: @@ -35,5 +37,17 @@ The following firewall ports are required for the Active Directory connector: | Port | Protocol | Description | | --- | --- | --- | | 389 | TCP | LDAP | +| 636 | TCP | LDAPS | | 135–139 | TCP | RPC | | Randomly allocated high TCP ports | TCP | RPC dynamic ports | + +## Least Privilege Model + +The following minimum permissions must be configured at the domain level in Active Directory: + +- Read access to directory tree +- List Contents and Read Property on the Deleted Objects Container + +:::note +See the Microsoft [Searching for Deleted Objects](https://technet.microsoft.com/en-us/library/cc978013.aspx) article and the Microsoft [Dsacls](https://technet.microsoft.com/en-us/library/cc771151(v=ws.11).aspx) article for additional information. +::: diff --git a/docs/accessanalyzer/2601/connectors/file-servers/cifs.md b/docs/accessanalyzer/2601/connectors/file-servers/cifs.md index e4ceab825e..dcf557fddc 100644 --- a/docs/accessanalyzer/2601/connectors/file-servers/cifs.md +++ b/docs/accessanalyzer/2601/connectors/file-servers/cifs.md @@ -8,7 +8,7 @@ sidebar_position: 10 Access Analyzer scans Windows file servers to enumerate files, folders, access permissions, and sensitive data. -Scanning can be performed directly from the Access Analyzer service (local mode) or via Scanners — Kubernetes-deployed containers for distributed scanning of remote environments. See the [Utilizing Scanners](../../scanners/overview.md) section for details on Scanner architecture. +Scanning can be performed directly from the Access Analyzer service (local mode) or via Scanners — Kubernetes-deployed containers for distributed scanning of remote environments. See the [Utilizing Scanners](../../configurations/source-groups/scanners/overview.md) section for details on Scanner architecture. ## Permissions diff --git a/docs/accessanalyzer/2601/connectors/sharepoint-online/_category_.json b/docs/accessanalyzer/2601/connectors/sharepoint-online/_category_.json index a8d05dd13b..aebbe26706 100644 --- a/docs/accessanalyzer/2601/connectors/sharepoint-online/_category_.json +++ b/docs/accessanalyzer/2601/connectors/sharepoint-online/_category_.json @@ -2,5 +2,9 @@ "label": "SharePoint Online", "position": 50, "collapsed": true, - "collapsible": true + "collapsible": true, + "link": { + "type": "doc", + "id": "connectors/sharepoint-online/overview" + } } diff --git a/docs/accessanalyzer/2601/connectors/sharepoint-online/overview.md b/docs/accessanalyzer/2601/connectors/sharepoint-online/overview.md new file mode 100644 index 0000000000..66e6768af4 --- /dev/null +++ b/docs/accessanalyzer/2601/connectors/sharepoint-online/overview.md @@ -0,0 +1,37 @@ +--- +title: "SharePoint Online" +description: "Requirements for connecting Access Analyzer to SharePoint Online" +sidebar_position: 1 +--- + +# SharePoint Online + +Access Analyzer connects to SharePoint Online using modern authentication, including support for multi-factor authentication (MFA). It authenticates through a pre-configured Microsoft Entra ID application and accesses SharePoint Online through Microsoft Graph and other modern APIs. + +Before adding SharePoint Online as a data source, you must register a dedicated Microsoft Entra ID application and grant it the required permissions. + +## Scan Types + +Access Analyzer supports two scan types for SharePoint Online: + +| Scan Type | Description | Authentication | +| --- | --- | --- | +| **Access scan** | Enumerates files, folders, and permissions to identify who has access to what | Client secret | +| **State-in-time scan** | Captures a permissions snapshot at a point in time for compliance and risk reporting | Certificate | + +Both scan types use the same registered Entra ID application. The certificate is an additional credential required only for state-in-time scans. + +## Before You Begin + +You need the following before adding SharePoint Online as a data source: + +- A user account with the **Global Administrator**, **Application Administrator**, or **Cloud Application Administrator** role in Microsoft Entra ID, to register an application and grant admin consent for permissions +- A registered Microsoft Entra ID application with the required API permissions — see [App Permissions in Entra](azure-permissions.md) +- A client secret generated for the registered application — see [Certificate Configuration](tenant-certificate-config.md) +- A certificate uploaded to the registered application (state-in-time scans only) — see [Certificate Configuration](tenant-certificate-config.md) + +When configuring the SharePoint Online source in Access Analyzer, you will need the following values from your registered application: + +- **Application (client) ID** +- **Directory (tenant) ID** +- **Client secret value** diff --git a/docs/accessanalyzer/2601/gettingstarted/active-directory-sync/active-directory.md b/docs/accessanalyzer/2601/gettingstarted/active-directory-sync/active-directory.md deleted file mode 100644 index f723d5e4a8..0000000000 --- a/docs/accessanalyzer/2601/gettingstarted/active-directory-sync/active-directory.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Active Directory Source Group" -description: "Making changes to an Active Directory source group wizard workflow" -sidebar_position: 10 ---- - -# Active Directory Source Group - -*Content coming soon.* diff --git a/docs/accessanalyzer/2601/gettingstarted/active-directory-sync/_category_.json b/docs/accessanalyzer/2601/gettingstarted/active-directory/_category_.json similarity index 61% rename from docs/accessanalyzer/2601/gettingstarted/active-directory-sync/_category_.json rename to docs/accessanalyzer/2601/gettingstarted/active-directory/_category_.json index fc2c06370c..78b3bd0452 100644 --- a/docs/accessanalyzer/2601/gettingstarted/active-directory-sync/_category_.json +++ b/docs/accessanalyzer/2601/gettingstarted/active-directory/_category_.json @@ -1,5 +1,5 @@ { - "label": "Scanning Active Directory", + "label": "Active Directory", "position": 20, "collapsed": true, "collapsible": true diff --git a/docs/accessanalyzer/2601/gettingstarted/active-directory/active-directory.md b/docs/accessanalyzer/2601/gettingstarted/active-directory/active-directory.md new file mode 100644 index 0000000000..dba78e02cd --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/active-directory/active-directory.md @@ -0,0 +1,32 @@ +--- +title: "Active Directory Scanning Overview" +description: "Overview of Active Directory scanning capabilities and prerequisites in Access Analyzer" +sidebar_position: 1 +--- + +# Active Directory Scanning Overview + +Access Analyzer scans Active Directory to inventory users, groups, group memberships, and organizational units across one or more domains. It detects security risks including stale accounts, privileged account exposure, excessive group nesting, and accounts with unusual delegation settings. Findings surface in the Active Directory Dashboard, giving security teams a clear picture of their identity posture and the data they need to prioritize remediation. + +## Prerequisites + +Before setting up an Active Directory source group, confirm that your environment meets the requirements below. The source group wizard connects to your domain controllers over LDAP or LDAPS, so the Access Analyzer server must be able to reach them on the network and a domain service account must be available with the appropriate read permissions. + +### Service Account + +Access Analyzer uses a domain service account to authenticate against your Active Directory domain controllers and read directory objects. The account must be a member of the domain you're scanning and have Read access to the directory tree. + +See [Username and Password](../../configurations/service-accounts/username-password.md) to create the service account and [Active Directory Connector Requirements](../../connectors/activedirectory.md) for the full list of required permissions. + +### Network Requirements + +| Protocol | Port | Destination | +| --- | --- | --- | +| LDAP | 389 | Domain controllers in the source group | +| LDAPS | 636 | Domain controllers in the source group (if using SSL) | + +### Before You Begin + +- The fully qualified domain name (FQDN) of each domain controller you plan to add. IP addresses are not supported — DIGEST-MD5 authentication requires a resolvable hostname and will fail if an IP address is provided. +- A Username and Password service account created in Access Analyzer with Read access to the domain. +- Network connectivity from the Access Analyzer server to port 389 or 636 on each domain controller confirmed. diff --git a/docs/accessanalyzer/2601/gettingstarted/active-directory/reports.md b/docs/accessanalyzer/2601/gettingstarted/active-directory/reports.md new file mode 100644 index 0000000000..51d8be3d72 --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/active-directory/reports.md @@ -0,0 +1,15 @@ +--- +title: "Reports" +description: "Pre-built dashboard available for Active Directory source groups in Access Analyzer" +sidebar_position: 50 +--- + +# Reports + +After the first Active Directory scan completes, the Active Directory Dashboard becomes available under the Dashboards section. The dashboard surfaces user and group inventory data alongside detected security risks, letting you answer questions such as how many privileged accounts exist in a domain, which users and groups carry the most risk findings, and what the overall distribution of risk severity looks like across your Active Directory environment. + +## Available reports + +| Location | Report | Description | +|----------|--------|-------------| +| Active Directory | Active Directory Dashboard | An overview of Active Directory scan results for one or more domains. Shows inventory counts for users, groups, and group memberships alongside security risk data, including risk breakdowns by type and severity and a ranked list of the objects with the highest number of associated risks. Filter by domain to focus on a specific part of your environment. | diff --git a/docs/accessanalyzer/2601/gettingstarted/active-directory/scanning-options.md b/docs/accessanalyzer/2601/gettingstarted/active-directory/scanning-options.md new file mode 100644 index 0000000000..f940fdae3c --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/active-directory/scanning-options.md @@ -0,0 +1,11 @@ +--- +title: "Available Scanning Options" +description: "Available scan types for Active Directory source groups" +sidebar_position: 2 +--- + +# Available Scanning Options + +| Scan Option | Description | Available Configurations | +| --- | --- | --- | +| **Active Directory Inventory** | Scans users, groups, and group memberships from all domain controllers in the source group. The first scan runs in full; subsequent scans run differentially, collecting only changes since the last run. | None | diff --git a/docs/accessanalyzer/2601/gettingstarted/active-directory/schema-reference.md b/docs/accessanalyzer/2601/gettingstarted/active-directory/schema-reference.md new file mode 100644 index 0000000000..28d9258a29 --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/active-directory/schema-reference.md @@ -0,0 +1,273 @@ +--- +title: "Active Directory Schema Reference" +sidebar_position: 40 +--- + +# Active Directory Schema Reference + +Access Analyzer stores Active Directory scan data in the `access_analyzer` ClickHouse database. The tables below are created when you set up an Active Directory source group and run a scan. Use this reference when querying scan data directly or integrating Access Analyzer data with external tools. + +:::note +All tables use the `ReplacingMergeTree` engine. Duplicate rows with the same primary key are deduplicated at merge time. Query the `_latest` views to return only the most recent version of each record. +::: + +## Metadata columns + +All tables include the following columns populated by Access Analyzer during each scan: + +| Column | Type | Description | +|--------|------|-------------| +| `scan_id` | `String` | Identifier of the source group that produced this record. | +| `scan_execution_id` | `String` | Identifier of the specific scan run. | +| `scanned_at` | `DateTime` | Timestamp when the record was written. | + +--- + +## Tables + +### active_directory_user + +Stores one row per user object discovered in an Active Directory scan. + +**Primary key:** `object_guid` + +#### Core identity fields + +| Column | Type | Description | +|--------|------|-------------| +| `object_guid` | `UUID` | Globally unique identifier for the user object. | +| `object_sid` | `String` | Security identifier (SID) of the user. | +| `distinguished_name` | `String` | Full distinguished name (DN) of the user in the directory. | +| `canonical_name` | `Nullable(String)` | Optional. Canonical form of the distinguished name. | +| `sam_account_name` | `String` | Pre-Windows 2000 logon name (sAMAccountName). | +| `user_principal_name` | `Nullable(String)` | Optional. User principal name (UPN) in `user@domain` format. | +| `display_name` | `Nullable(String)` | Optional. Display name shown in directory listings. | +| `given_name` | `Nullable(String)` | Optional. First name of the user. | +| `surname` | `Nullable(String)` | Optional. Last name of the user. | +| `enabled` | `Bool` | Whether the user account is enabled. | +| `when_created` | `Nullable(DateTime)` | Optional. Timestamp when the account was created in the directory. | +| `when_changed` | `Nullable(DateTime)` | Optional. Timestamp of the most recent change to the account. | +| `description` | `Nullable(String)` | Optional. Description field set on the user object. | +| `admin_count` | `Nullable(Int32)` | Optional. Value of the `adminCount` attribute; non-zero values indicate the account is or was protected by AdminSDHolder. | +| `primary_group_id` | `Nullable(Int32)` | Optional. Relative identifier (RID) of the user's primary group. | +| `domain_name` | `Nullable(String)` | Optional. NetBIOS or DNS name of the domain. | +| `domain_canonical_name` | `Nullable(String)` | Optional. Canonical (DNS) name of the domain. | +| `cn` | `Nullable(String)` | Optional. Common name (CN) attribute of the user object. | + +#### Contact information + +| Column | Type | Description | +|--------|------|-------------| +| `mail` | `Nullable(String)` | Optional. Email address. | +| `telephone_number` | `Nullable(String)` | Optional. Office telephone number. | +| `mobile` | `Nullable(String)` | Optional. Mobile telephone number. | +| `office` | `Nullable(String)` | Optional. Office location. | +| `street_address` | `Nullable(String)` | Optional. Street address. | +| `city` | `Nullable(String)` | Optional. City. | +| `state` | `Nullable(String)` | Optional. State or province. | +| `postal_code` | `Nullable(String)` | Optional. Postal or ZIP code. | +| `country` | `Nullable(String)` | Optional. Country or region. | + +#### Organizational information + +| Column | Type | Description | +|--------|------|-------------| +| `job_title` | `Nullable(String)` | Optional. Job title. | +| `department` | `Nullable(String)` | Optional. Department. | +| `company` | `Nullable(String)` | Optional. Company or organization name. | +| `manager_dn` | `Nullable(String)` | Optional. Distinguished name of the user's manager. | +| `employee_id` | `Nullable(String)` | Optional. Employee identifier. | + +#### Security information + +| Column | Type | Description | +|--------|------|-------------| +| `user_account_control` | `Nullable(Int32)` | Optional. Bitmask value of the `userAccountControl` attribute controlling account behavior and flags. | +| `password_last_set` | `Nullable(DateTime)` | Optional. Timestamp when the password was last changed. | +| `password_never_expires` | `Nullable(Bool)` | Optional. Whether the password is set to never expire. | +| `account_expires` | `Nullable(String)` | Optional. Expiration date of the account, stored as a string representation of the directory value. | +| `logon_hours` | `Nullable(String)` | Optional. Bitmask string representing the hours during which the user is permitted to log on. | +| `logon_workstations` | `Array(String)` | List of workstations the user is permitted to log on to; empty array indicates no restriction. | +| `smartcard_required` | `Nullable(Bool)` | Optional. Whether the account requires a smart card to log on. | +| `mfa_enforced` | `Nullable(Bool)` | Optional. Whether multi-factor authentication is enforced for this account. | +| `is_deleted` | `Boolean` | Whether the user object has been soft-deleted. Rows where `is_deleted = 1` are excluded from the `active_directory_user_latest` view. | + +#### Activity information + +| Column | Type | Description | +|--------|------|-------------| +| `last_logon` | `Nullable(DateTime)` | Optional. Most recent logon timestamp from the domain controller that serviced the last logon. Not replicated across domain controllers. | +| `last_logon_timestamp` | `Nullable(DateTime)` | Optional. Replicated logon timestamp (`lastLogonTimestamp`); updated at intervals and may lag behind the actual last logon by up to 14 days. | +| `bad_pwd_count` | `Nullable(Int32)` | Optional. Number of consecutive failed logon attempts. | +| `bad_password_time` | `Nullable(DateTime)` | Optional. Timestamp of the last failed logon attempt. | +| `lockout_time` | `Nullable(DateTime)` | Optional. Timestamp when the account was locked out; `NULL` or zero indicates the account is not locked. | +| `last_logoff` | `Nullable(DateTime)` | Optional. Timestamp of the last logoff. | + +#### Delegation information + +| Column | Type | Description | +|--------|------|-------------| +| `ms_ds_allowed_to_act_on_behalf_of` | `Array(String)` | List of security descriptors for accounts permitted to delegate to this account using resource-based constrained delegation. | +| `ms_ds_allowed_to_delegate_to` | `Array(String)` | List of SPNs this account is permitted to delegate to using constrained delegation. | +| `ms_ds_supported_encryption_types` | `Nullable(Int32)` | Optional. Bitmask of Kerberos encryption types supported by this account. | +| `service_principal_name` | `Array(String)` | List of service principal names (SPNs) registered to this account. | +| `legacy_exchange_dn` | `Nullable(String)` | Optional. Legacy Exchange distinguished name, used for mail routing compatibility. | +| `ms_ds_user_account_control_computer` | `Nullable(Int32)` | Optional. Computer-specific `userAccountControl` flags stored on the user object in hybrid environments. | + +**Relations** + +| Related table | Join column | Description | +|---|---|---| +| `active_directory_group_membership` | `object_sid` via `foreign_sid` | Resolves groups that include this user when the user was added by SID from a foreign domain. | +| `active_directory_group_membership` | `distinguished_name` via `member_dn` | Resolves groups that include this user when the user was added by DN. | +| `active_directory_user_custom_attribute` | `object_guid` | Returns custom attribute values collected for this user. | +| `active_directory_effective_group_membership` | `object_guid` via `member_object_guid` | Returns all groups this user belongs to, including nested memberships. | + +--- + +### active_directory_group + +Stores one row per group object discovered in an Active Directory scan. + +**Primary key:** `object_guid` + +| Column | Type | Description | +|--------|------|-------------| +| `object_guid` | `UUID` | Globally unique identifier for the group object. | +| `object_sid` | `String` | Security identifier (SID) of the group. | +| `distinguished_name` | `String` | Full distinguished name (DN) of the group in the directory. | +| `sam_account_name` | `Nullable(String)` | Optional. Pre-Windows 2000 name of the group. | +| `name` | `Nullable(String)` | Optional. Display name of the group. | +| `group_scope` | `Nullable(String)` | Optional. Scope of the group: `DomainLocal`, `Global`, or `Universal`. | +| `group_type` | `Nullable(String)` | Optional. Type of the group: `Security` or `Distribution`. | +| `admin_count` | `Nullable(Int32)` | Optional. Value of the `adminCount` attribute; non-zero values indicate the group is or was protected by AdminSDHolder. | +| `primary_group_id` | `Nullable(Int32)` | Optional. Relative identifier (RID) associated with this group when it is used as a primary group. | +| `domain_name` | `Nullable(String)` | Optional. NetBIOS or DNS name of the domain. | +| `domain_canonical_name` | `Nullable(String)` | Optional. Canonical (DNS) name of the domain. | +| `cn` | `Nullable(String)` | Optional. Common name (CN) attribute of the group object. | +| `mail` | `Nullable(String)` | Optional. Email address associated with the group. | +| `is_deleted` | `Boolean` | Whether the group object has been soft-deleted. Rows where `is_deleted = 1` are excluded from the `active_directory_group_latest` view. | + +**Relations** + +| Related table | Join column | Description | +|---|---|---| +| `active_directory_group_membership` | `distinguished_name` via `group_dn` | Lists the direct members of this group. | +| `active_directory_effective_group_membership` | `object_guid` via `group_object_guid` | Lists all effective members of this group, including nested members. | + +--- + +### active_directory_group_membership + +Stores one row per direct membership relationship between a group and a member object (user or group). Nesting is not flattened in this table; use `active_directory_effective_group_membership` for flattened membership. + +**Primary key:** `(group_dn, member_dn)` + +| Column | Type | Description | +|--------|------|-------------| +| `group_dn` | `String` | Distinguished name (DN) of the group. | +| `member_dn` | `String` | Distinguished name (DN) of the member object. | +| `foreign_sid` | `Nullable(String)` | Optional. SID of the member when the member is from a foreign (trusted) domain and a DN is not available. | + +**Relations** + +| Related table | Join column | Description | +|---|---|---| +| `active_directory_group` | `group_dn` = `distinguished_name` | Resolves the group record for this membership row. | +| `active_directory_user` | `member_dn` = `distinguished_name` | Resolves the user record for this membership row when the member is a user. | +| `active_directory_group` | `member_dn` = `distinguished_name` | Resolves the group record for this membership row when the member is a nested group. | +| `active_directory_user` | `foreign_sid` = `object_sid` | Resolves a foreign-domain user by SID when `foreign_sid` is set. | +| `active_directory_group` | `foreign_sid` = `object_sid` | Resolves a foreign-domain group by SID when `foreign_sid` is set. | + +--- + +### active_directory_user_custom_attribute + +Stores custom Active Directory attribute values collected for user objects during a scan. Each row represents one attribute key-value pair for one user. An attribute with no value produces a row with `attr_value = NULL`. + +**Primary key:** `(object_guid, attr_name)` + +| Column | Type | Description | +|--------|------|-------------| +| `object_guid` | `UUID` | Globally unique identifier of the user object. Joins to `active_directory_user.object_guid`. | +| `attr_name` | `String` | LDAP attribute name, as configured in the source group settings. | +| `attr_value` | `Nullable(String)` | Optional. String representation of the attribute value. | + +**Relations** + +| Related table | Join column | Description | +|---|---|---| +| `active_directory_user` | `object_guid` | Returns the full user record for this custom attribute row. | + +--- + +### active_directory_effective_group_membership + +Stores the fully flattened, transitively resolved group membership graph. This table is populated by the `active_directory_effective_group_membership_mv` materialized view, which refreshes on a schedule after each scan. Each row represents one effective membership relationship at a given nesting depth. + +**Engine:** `MergeTree` (not `ReplacingMergeTree`). The table is rebuilt on each refresh rather than deduplicated by version. + +**Primary key:** `(group_object_guid, member_object_guid)` + +| Column | Type | Description | +|--------|------|-------------| +| `group_object_guid` | `UUID` | Globally unique identifier of the group. Joins to `active_directory_group.object_guid`. | +| `member_object_guid` | `UUID` | Globally unique identifier of the effective member (user or group). Joins to `active_directory_user.object_guid` or `active_directory_group.object_guid`. | +| `nesting_level` | `Int32` | Depth of the membership relationship. A value of `0` indicates direct membership; higher values indicate the number of intermediate groups. | + +**Relations** + +| Related table | Join column | Description | +|---|---|---| +| `active_directory_group` | `group_object_guid` = `object_guid` | Resolves the group name and attributes for this membership row. | +| `active_directory_user` | `member_object_guid` = `object_guid` | Resolves the user record when the effective member is a user. | +| `active_directory_group` | `member_object_guid` = `object_guid` | Resolves the group record when the effective member is a nested group. | + +--- + +## Views + +Access Analyzer creates views that simplify common queries. Use views in preference to querying base tables directly. + +### Deduplication views + +These views apply `FINAL` to the underlying `ReplacingMergeTree` tables to return only the most recent version of each record. Use these as the starting point for any query against Active Directory data. + +| View | Base table | Description | +|------|------------|-------------| +| `active_directory_user_latest` | `active_directory_user` | Returns the most recent version of each user record, deduplicated by `object_guid`, excluding soft-deleted users (`is_deleted = 1`). | +| `active_directory_group_latest` | `active_directory_group` | Returns the most recent version of each group record, deduplicated by `object_guid`, excluding soft-deleted groups (`is_deleted = 1`). | +| `active_directory_group_membership_latest` | `active_directory_group_membership` | Returns the most recent version of each group membership row, deduplicated by `(group_dn, member_dn)`. | +| `active_directory_user_custom_attribute_latest` | `active_directory_user_custom_attribute` | Returns the most recent version of each custom attribute row, deduplicated by `(object_guid, attr_name)`. | + +### Resolution views + +These views resolve raw membership data into UUID-keyed relationships. + +| View | Description | +|------|-------------| +| `active_directory_group_membership_resolved` | Joins `active_directory_group_membership_latest` to the user and group tables to produce a resolved membership graph keyed by `(group_object_guid, member_object_guid)`. Handles both same-domain members (matched by DN) and foreign-domain members (matched by SID). Excludes deleted objects. Used as the source for `active_directory_effective_group_membership_mv`. | + +### Risk views + +These views surface specific account and group hygiene conditions. Each view returns rows in a common shape: `risk_type`, `entity_id`, `entity_name`, `domain`, `detection_timestamp`, and `additional_context`. The `active_directory_risks_summary` view aggregates all risk views into a single result set enriched with catalog metadata. + +| View | Description | +|------|-------------| +| `active_directory_empty_groups` | Groups that have no effective members. | +| `active_directory_single_member_groups` | Groups that have exactly one effective member. | +| `active_directory_large_groups` | Groups that have more than 500 effective members. | +| `active_directory_duplicate_groups_mv` | Groups whose effective membership set is identical to that of at least one other group. | +| `active_directory_circular_nesting_mv` | Groups involved in circular nesting or with a nesting depth of 10 or more. | +| `active_directory_stale_users` | Enabled user accounts with no logon activity in the past 90 to 365 days. | +| `active_directory_very_stale_users` | Enabled user accounts with no logon activity for more than 365 days. | +| `active_directory_isolated_users` | Enabled user accounts that belong to no groups. | +| `active_directory_no_logon_users` | Enabled user accounts with no recorded logon timestamp. | +| `active_directory_password_never_expires` | Enabled user accounts configured with a non-expiring password. | +| `active_directory_password_not_required` | Enabled user accounts where the `PASSWD_NOTREQD` flag is set in `user_account_control`. | +| `active_directory_old_passwords` | Enabled user accounts whose password has not changed in more than 90 days. | +| `active_directory_dc_logon_rights` | Enabled users who are effective members of privileged groups that grant domain controller logon rights (for example, Domain Admins, Enterprise Admins). | +| `active_directory_risks_summary_mv` | Union of all individual risk views. Returns one row per detected risk. | +| `active_directory_risks_summary` | Enriches `active_directory_risks_summary_mv` with risk level, category, and description from the `active_directory_risk_catalog` reference table. Use this view to query all risks with their human-readable metadata. | +| `active_directory_risks_by_domain` | Aggregates risk counts by domain and risk type, sourced from `active_directory_risks_summary_mv`. | +| `active_directory_group_member_counts` | Returns the total effective member count for each group. Intermediate view used by the group risk views. | diff --git a/docs/accessanalyzer/2601/gettingstarted/active-directory/set-up-source-group.md b/docs/accessanalyzer/2601/gettingstarted/active-directory/set-up-source-group.md new file mode 100644 index 0000000000..571b505731 --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/active-directory/set-up-source-group.md @@ -0,0 +1,57 @@ +--- +title: "Set Up Active Directory Source Group" +description: "Configure an Active Directory source group in Access Analyzer" +sidebar_position: 3 +--- + +# Active Directory Source Group + +**Step 1 –** Navigate to **Configuration** > **Source Groups** and click **Add Source**. The source group wizard opens. + +**Step 2 –** Select **Active Directory** and click **Next**. + +**Step 3 –** Enter a **Source Group Name**. + +**Step 4 –** Select a service account from the **Service Account** dropdown, or click **+** to create one inline. Service accounts store the credentials Access Analyzer uses to connect to your domain controllers. See [Service Accounts](../../configurations/service-accounts/overview.md) for details. + +**Step 5 –** Click **Add** under **Domain Controllers**, then select **Add Manually**. + +**Step 6 –** Enter the following for each domain controller: + +- **Server Name / IP** — The FQDN of the domain controller. To add multiple domain controllers, separate entries with a comma or press **Enter** after each one. +- **Domain** — The DNS domain name (for example, `corp.example.com`). Applied to all entries above. +- **Port** — The LDAP port. Default is `389`. Use `636` for LDAPS. + +**Step 7 –** Click **Add domain controller**, then click **Done**. Repeat Steps 5–7 for each additional domain. + +**Step 8 –** If your domain controllers use self-signed certificates on port 636, select **Ignore SSL errors**. + +**Step 9 –** Click **Test Connection** to verify connectivity. Each domain controller displays a **Connected** or **Failed** status. Resolve any failures before proceeding. + +**Step 10 –** Click **Next**. + +**Step 11 –** Under **Scanner Location**, select **System scanner** to run scans from the Access Analyzer service, or select **Custom scanner** to use a deployed scanner. See [Scanners](../../configurations/source-groups/scanners/overview.md) for details. + +**Step 12 –** Under **Scan Schedule**, select when to run the scan: + +- **Now** — Starts the scan immediately after setup completes. +- **At** — Runs the scan once at a specific date and time. +- **Advanced** — Runs the scan on a recurring schedule defined by a cron expression. + +**Step 13 –** Click **Complete Setup**. + +## What Happens Next + +Access Analyzer creates the source group and a scan for each domain controller you added. If you selected **Now**, the Active Directory Inventory scan starts immediately. + +To check scan progress, navigate to **Configuration** > **Scan Executions**. + +To view results after the scan completes, see [Active Directory Dashboard](../../dashboards-reports/active-directory-dashboard/overview.md). + +## Edit a Source Group + +To modify an existing Active Directory source group, navigate to **Configuration** > **Source Groups**, select the source group, and click **Edit**. The wizard reopens with your current configuration pre-populated. You can update the source group name, service account, domain controllers, and scan schedule. + +:::note +Updating the service account affects all domain controllers in the source group, as they share a single set of credentials. +::: diff --git a/docs/accessanalyzer/2601/gettingstarted/activity-data/_category_.json b/docs/accessanalyzer/2601/gettingstarted/activity-data/_category_.json deleted file mode 100644 index e008bc29bf..0000000000 --- a/docs/accessanalyzer/2601/gettingstarted/activity-data/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Collecting Activity Data", - "position": 70, - "collapsed": true, - "collapsible": true -} diff --git a/docs/accessanalyzer/2601/gettingstarted/activity-data/file-server-activity.md b/docs/accessanalyzer/2601/gettingstarted/activity-data/file-server-activity.md deleted file mode 100644 index 41114e0caa..0000000000 --- a/docs/accessanalyzer/2601/gettingstarted/activity-data/file-server-activity.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "File Server Activity" -description: "Start collecting file server activity data" -sidebar_position: 10 ---- - -# File Server Activity - -*Content coming soon.* diff --git a/docs/accessanalyzer/2601/gettingstarted/activity-monitor-integration/_category_.json b/docs/accessanalyzer/2601/gettingstarted/activity-monitor-integration/_category_.json deleted file mode 100644 index 130074f727..0000000000 --- a/docs/accessanalyzer/2601/gettingstarted/activity-monitor-integration/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Activity Monitor Integration", - "position": 80, - "collapsed": true, - "collapsible": true -} diff --git a/docs/accessanalyzer/2601/gettingstarted/activity-monitor-integration/overview.md b/docs/accessanalyzer/2601/gettingstarted/activity-monitor-integration/overview.md deleted file mode 100644 index b76c72252c..0000000000 --- a/docs/accessanalyzer/2601/gettingstarted/activity-monitor-integration/overview.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Activity Monitor Integration" -description: "Configure Activity Monitor integration with Access Analyzer" -sidebar_position: 10 ---- - -# Activity Monitor Integration - -*Content coming soon.* diff --git a/docs/accessanalyzer/2601/gettingstarted/entra-id-sync/entra-id.md b/docs/accessanalyzer/2601/gettingstarted/entra-id-sync/entra-id.md deleted file mode 100644 index 787bb89c41..0000000000 --- a/docs/accessanalyzer/2601/gettingstarted/entra-id-sync/entra-id.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Entra ID Source Group" -description: "Making changes to an Entra ID source group wizard workflow" -sidebar_position: 30 ---- - -# Entra ID Source Group - -*Content coming soon.* diff --git a/docs/accessanalyzer/2601/gettingstarted/entra-id-sync/_category_.json b/docs/accessanalyzer/2601/gettingstarted/entra-id/_category_.json similarity index 67% rename from docs/accessanalyzer/2601/gettingstarted/entra-id-sync/_category_.json rename to docs/accessanalyzer/2601/gettingstarted/entra-id/_category_.json index b4785d5d62..03206793dc 100644 --- a/docs/accessanalyzer/2601/gettingstarted/entra-id-sync/_category_.json +++ b/docs/accessanalyzer/2601/gettingstarted/entra-id/_category_.json @@ -1,5 +1,5 @@ { - "label": "Scanning Entra ID", + "label": "Entra ID", "position": 40, "collapsed": true, "collapsible": true diff --git a/docs/accessanalyzer/2601/gettingstarted/entra-id/entra-id.md b/docs/accessanalyzer/2601/gettingstarted/entra-id/entra-id.md new file mode 100644 index 0000000000..9465add534 --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/entra-id/entra-id.md @@ -0,0 +1,34 @@ +--- +title: "Entra ID Scanning Overview" +description: "Overview of Entra ID scanning capabilities and prerequisites in Access Analyzer" +sidebar_position: 1 +--- + +# Entra ID Scanning Overview + +Access Analyzer connects to Microsoft Entra ID to synchronize Microsoft Information Protection (MIP) sensitivity labels from your tenant. These labels — assigned through Microsoft Purview — are applied to files on Windows file servers and appear alongside Access Analyzer's own sensitive data findings. Integrating MIP labels gives you a unified view of sensitive data classification that spans both Access Analyzer's built-in classifiers and your organization's custom Purview sensitivity taxonomy. + +## Prerequisites + +Before setting up an Entra ID source group, confirm that your environment meets the requirements below. The source group wizard connects to Microsoft Entra ID over HTTPS using a registered application's client credentials, so the Access Analyzer server must be able to reach the Microsoft identity platform and an app registration must be configured in your tenant with the required API permissions. + +### Service Account + +Access Analyzer uses a Client ID and Secret service account to authenticate with Microsoft Entra ID via the Microsoft Graph API. This requires a registered application in your Entra ID tenant with the appropriate API permissions granted and a client secret generated for that application. + +See [Entra ID Service Account](../../configurations/service-accounts/entra-id.md) to create the service account and [Entra ID Requirements](../../connectors/entra-id/overview.md) for instructions on registering the application and granting the required permissions. + +### Network Requirements + +| Protocol | Port | Destination | +| --- | --- | --- | +| HTTPS | 443 | Microsoft identity platform (`login.microsoftonline.com`) | +| HTTPS | 443 | Microsoft Graph API (`graph.microsoft.com`) | + +### Before You Begin + +- A registered application in your Entra ID tenant with the required API permissions granted. +- The application's **Tenant ID** and **Client ID**. +- A client secret generated for the application. +- A Client ID and Secret service account created in Access Analyzer. +- Network connectivity from the Access Analyzer server to port 443 confirmed. diff --git a/docs/accessanalyzer/2601/gettingstarted/entra-id/scanning-options.md b/docs/accessanalyzer/2601/gettingstarted/entra-id/scanning-options.md new file mode 100644 index 0000000000..0edc749d8a --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/entra-id/scanning-options.md @@ -0,0 +1,11 @@ +--- +title: "Available Scanning Options" +description: "Available scan types for Entra ID source groups" +sidebar_position: 2 +--- + +# Available Scanning Options + +| Scan Option | Description | Available Configurations | +| --- | --- | --- | +| **Users, Groups, and Roles** | Scans Entra ID users, groups, and role assignments. The first scan runs in full; subsequent scans run differentially, collecting only changes since the last run. | None | diff --git a/docs/accessanalyzer/2601/gettingstarted/entra-id/set-up-source-group.md b/docs/accessanalyzer/2601/gettingstarted/entra-id/set-up-source-group.md new file mode 100644 index 0000000000..678964f440 --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/entra-id/set-up-source-group.md @@ -0,0 +1,45 @@ +--- +title: "Set Up Entra ID Source Group" +description: "Configure an Entra ID source group in Access Analyzer" +sidebar_position: 3 +--- + +# Set Up Entra ID Source Group + +**Step 1 –** Navigate to **Configuration** > **Source Groups** and click **Add Source**. The source group wizard opens. + +**Step 2 –** Select **Entra ID** and click **Next**. + +**Step 3 –** Enter a **Source Group Name**. + +**Step 4 –** Select a service account from the **Service Account** dropdown, or click **+** to create one inline. Entra ID requires a **Client ID and Secret** service account type. See [Service Accounts](../../configurations/service-accounts/overview.md) for details. + +**Step 5 –** Enter the **Tenant ID** for your Entra ID directory. This must be a valid UUID (for example, `550e8400-e29b-41d4-a716-446655440000`). + +**Step 6 –** Click **Test Connection** to verify that Access Analyzer can authenticate to your Entra ID tenant. Resolve any failures before proceeding. + +**Step 7 –** Click **Next**. + +**Step 8 –** Under **Scanner Location**, the scanner is set to **System scanner** and cannot be changed. Entra ID scans run from the Access Analyzer service only. + +**Step 9 –** Under **Scan Schedule**, select when to run the scan: + +- **Now** — Starts the scan immediately after setup completes. +- **At** — Runs the scan once at a specific date and time. +- **Advanced** — Runs the scan on a recurring schedule defined by a cron expression. + +**Step 10 –** Click **Complete Setup**. + +## What Happens Next + +Access Analyzer creates the source group and begins syncing users, groups, and roles from your Entra ID tenant. If you selected **Now**, the scan starts immediately. + +To check scan progress, navigate to **Configuration** > **Scan Executions**. + +## Edit a Source Group + +To modify an existing Entra ID source group, navigate to **Configuration** > **Source Groups**, select the source group, and click **Edit**. The wizard reopens with your current configuration pre-populated. You can update the source group name, service account, tenant ID, and scan schedule. + +:::note +Updating the service account replaces the client credentials used to authenticate with Entra ID. Ensure the new service account has the required API permissions before saving. +::: diff --git a/docs/accessanalyzer/2601/gettingstarted/file-server-scans/file-server.md b/docs/accessanalyzer/2601/gettingstarted/file-server-scans/file-server.md deleted file mode 100644 index 7186761125..0000000000 --- a/docs/accessanalyzer/2601/gettingstarted/file-server-scans/file-server.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "File Server Source Group" -description: "Making changes to a File Server source group wizard workflow" -sidebar_position: 20 ---- - -# File Server Source Group - -*Content coming soon.* diff --git a/docs/accessanalyzer/2601/gettingstarted/file-server-scans/_category_.json b/docs/accessanalyzer/2601/gettingstarted/file-servers/_category_.json similarity index 64% rename from docs/accessanalyzer/2601/gettingstarted/file-server-scans/_category_.json rename to docs/accessanalyzer/2601/gettingstarted/file-servers/_category_.json index 4771d2c62e..dbe2c40136 100644 --- a/docs/accessanalyzer/2601/gettingstarted/file-server-scans/_category_.json +++ b/docs/accessanalyzer/2601/gettingstarted/file-servers/_category_.json @@ -1,5 +1,5 @@ { - "label": "Scanning File Servers", + "label": "File Servers", "position": 30, "collapsed": true, "collapsible": true diff --git a/docs/accessanalyzer/2601/gettingstarted/file-servers/file-servers.md b/docs/accessanalyzer/2601/gettingstarted/file-servers/file-servers.md new file mode 100644 index 0000000000..18cefa7115 --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/file-servers/file-servers.md @@ -0,0 +1,31 @@ +--- +title: "File Server Scanning Overview" +description: "Overview of file server scanning capabilities and prerequisites in Access Analyzer" +sidebar_position: 1 +--- + +# File Server Scanning Overview + +Access Analyzer scans file servers over SMB to map share permissions, folder-level ACLs, and file ownership across your environment. It can also scan file contents to locate sensitive data and, if activity monitoring is configured, track file access events over time. Reports surface open access, broken inheritance, direct user permissions, and sensitive data exposure — giving security and compliance teams the visibility they need to reduce unnecessary access and meet data protection requirements. + +## Prerequisites + +Before setting up a file server source group, confirm that your environment meets the requirements below. The source group wizard connects to your Windows file servers over SMB, so the Access Analyzer server must be able to reach them on the network and a domain service account must be available with the permissions required for the scan types you plan to enable. + +### Service Account + +Access Analyzer uses a domain service account to authenticate against your Windows file servers over SMB and enumerate shares, permissions, and file contents. The account must be a member of the same domain as the target file servers. The specific permissions required depend on the scan types you enable — access scanning and sensitive data scanning have different requirements. + +See [Username and Password](../../configurations/service-accounts/username-password.md) to create the service account and [CIFS / SMB File Share](../../connectors/file-servers/cifs.md) for the full list of required permissions by scan type. + +### Network Requirements + +| Protocol | Port | Destination | +| --- | --- | --- | +| SMB | 445 | Windows file servers in the source group | + +### Before You Begin + +- The hostname or IP address of each file server you plan to add. +- A Username and Password service account created in Access Analyzer with the appropriate permissions on the target file servers. +- Network connectivity from the Access Analyzer server to port 445 on each file server confirmed. diff --git a/docs/accessanalyzer/2601/gettingstarted/file-servers/reports.md b/docs/accessanalyzer/2601/gettingstarted/file-servers/reports.md new file mode 100644 index 0000000000..9d23d9f9b4 --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/file-servers/reports.md @@ -0,0 +1,31 @@ +--- +title: "Reports" +description: "Pre-built reports available for File Servers source groups in Access Analyzer" +sidebar_position: 50 +--- + +# Reports + +File Servers source groups include a set of pre-built reports that answer common security questions about permissions, sensitive data exposure, access patterns, and data content across your CIFS/SMB file shares. Reports are available under the Reports section after the first scan completes and update each time a scan runs. + +## Available reports + +| Location | Report | Description | +|----------|--------|-------------| +| Access / Broken Inheritance | Broken Inheritance | Lists shares and folders where permission inheritance has been broken, meaning the folder's ACL no longer follows its parent. Use this report to find locations where custom permission assignments may have introduced inconsistencies or unexpected access. | +| Access / Domain User ACLs | Domain User ACLs | Shows share and folder permissions assigned directly to domain user accounts. Use this report to identify accounts with direct ACL entries that should be managed through groups instead. | +| Access / High Risk ACLs | High Risk ACLs | Identifies folders where broad trustees such as Everyone, Authenticated Users, or Domain Users appear in the access control list. Use this report to locate and remediate over-permissioned folders that expose data to wide audiences. | +| Access / Local Administrators | Local Administrators | Lists local administrator accounts and the hosts where they hold that privilege. Use this report to identify non-standard or unauthorized local administrator assignments across your file servers. | +| Access / Missing Full Control | Missing Full Control | Lists folders where no trustee holds Full Control permission. Use this report to identify folders that may lack a clear owner or administrator and address potential access management gaps. | +| Access / Open Access | Open Access | Identifies folders and shares accessible to broad groups or where sensitive data is reachable without restriction. Use this report to prioritize remediation of the most exposed locations in your file server environment. | +| Access / Probable Owner | Probable Owner | Identifies the most likely owner for each share based on access patterns and file activity. Use this report to assign data ownership and support data governance workflows. | +| Access / Share Audit | Share Audit | Provides a detailed breakdown of share-level attributes including scan status, last scanned date, file counts, object counts, and active users. Use this report to confirm scan coverage and review the overall state of each share. | +| Activity / Activity Investigation | Activity Investigation | Displays file system events filtered by date range, user, path, and event type. Use this report to trace the actions of a specific user or investigate changes to a specific file or folder. | +| Content / Empty Shares | Empty Shares | Lists shares that contain no files. Use this report to identify shares that can be reviewed for decommissioning or consolidation. | +| Content / Largest Shares | Largest Shares | Ranks file shares by total size. Use this report to identify shares that consume the most storage and prioritize them for review or cleanup. | +| Content / Nested Shares | Nested Shares | Identifies shares that are nested inside other shares, creating multiple access paths to the same data with potentially different permissions. Use this report to find and resolve configurations that complicate permission management and access auditing. | +| Content / Stale Content | Stale Content | Identifies files and shares that haven't been accessed within a configurable threshold. Use this report to locate data that may be a candidate for archiving, deletion, or access review. | +| Sensitive Data / Sensitive Data Activity | Sensitive Data Activity | Shows file system events involving files that contain sensitive data, filtered by date range, event type, user, and classification taxonomy. Use this report to identify who is reading, modifying, or deleting sensitive files and to detect potential data exfiltration or misuse. | +| Sensitive Data / Sensitive Data Overview | Sensitive Data Overview | Provides a high-level summary of sensitive data scan findings across CIFS/SMB file shares, including the number of files with matches, classification terms found, and distribution by host and share. Use this report as a starting point for understanding where sensitive data lives in your file server environment. | +| Sensitive Data / Share Audit | Share Audit | Shows share-level details in the context of sensitive data findings, including which shares contain files with sensitive data matches. Use this report to understand sensitive data distribution across shares and prioritize remediation. | +| Sensitive Data / Stale Data | Stale Data | Identifies files containing sensitive data that haven't been accessed recently. Use this report to find aging sensitive content that may no longer be actively used but still carries exposure risk. | diff --git a/docs/accessanalyzer/2601/gettingstarted/file-servers/scanning-options.md b/docs/accessanalyzer/2601/gettingstarted/file-servers/scanning-options.md new file mode 100644 index 0000000000..c80cdd296d --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/file-servers/scanning-options.md @@ -0,0 +1,28 @@ +--- +title: "Available Scanning Options" +description: "Available scan types and configuration options for file server source groups" +sidebar_position: 2 +--- + +# Available Scanning Options + +| Scan Option | Description | Available Configurations | +| --- | --- | --- | +| **Access** | Scans file server permissions and access controls to identify who has access to what. | Share selection (all shares or custom), file-level permissions, concurrent workers (1–20) | +| **Sensitive Data** | Scans file contents for sensitive data patterns such as PII, credentials, PHI, and financial records. The first scan runs in full; subsequent scans run differentially, collecting only changes since the last run. | Share selection (all shares or custom), sensitive data types, OCR, differential scan | + +## Scan Configuration + +**Access** + +- **Include Shares** — Select **All shares** to scan every share on the server, or **Custom selection** to specify which shares to include. +- **Exclude Shares** — Enter share paths to skip. Wildcards are supported (for example, `\\fileserver\*\temp*`). +- **Hidden shares** — Select **Automatically enumerate hidden shares** to include hidden shares. Use **Exclude Hidden Shares** to skip specific ones (for example, `ADMIN$, C$, IPC$`). +- **File-level permissions** — Select **Include file-level permission data** to collect permissions at the individual file level in addition to folder level. This increases scan time. +- **Workers** — Sets the number of concurrent enumeration threads. Default is `3`; valid range is `1–20`. Increase to improve scan speed; decrease to reduce load on the file server. + +**Sensitive Data** + +- **Include/Exclude Shares** — Same share selection options as the Access scan. +- **Sensitive data types** — Select **Inherit from Global Settings** to use the system-wide classification configuration, or disable this option to configure types for this source group. Enable each type you want to detect and assign a classification label. +- **OCR** — Select **Run OCR** to scan images, screenshots, and scanned documents for sensitive text. This increases processing time. diff --git a/docs/accessanalyzer/2601/gettingstarted/file-servers/schema-reference.md b/docs/accessanalyzer/2601/gettingstarted/file-servers/schema-reference.md new file mode 100644 index 0000000000..47e0de6ab2 --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/file-servers/schema-reference.md @@ -0,0 +1,201 @@ +--- +title: "File Servers Schema Reference" +sidebar_position: 40 +--- + +# File Servers Schema Reference + +Access Analyzer stores File Server scan data in the `access_analyzer` ClickHouse database. The tables below are created when you set up a File Server source group and run a scan. Use this reference when querying scan data directly or integrating Access Analyzer data with external tools. + +:::note +All tables use the `ReplacingMergeTree` engine. Duplicate rows with the same primary key are deduplicated at merge time. Query the `_latest` views to return only the most recent version of each record. +::: + +## Metadata columns + +All tables include the following columns populated by Access Analyzer during each scan: + +| Column | Type | Description | +|--------|------|-------------| +| `scan_id` | `String` | Identifier of the source group that produced this record. | +| `scan_execution_id` | `String` | Identifier of the specific scan run. | +| `scanned_at` | `DateTime` | Timestamp when the record was written. | + +--- + +## Tables + +### cifs_object + +Stores the file system inventory collected during a scan — one row per file, directory, or share discovered on a file server. + +| Column | Type | Description | +|--------|------|-------------| +| `host` | `String` | Hostname of the file server. | +| `share_name` | `String` | Name of the share on the file server. | +| `share_path` | `String` | UNC path of the share root. | +| `path` | `String` | Full path of the object within the share. | +| `object_type` | `Enum8('FILE', 'DIRECTORY', 'SHARE')` | Whether the object is a file, directory, or share. | +| `parent_path` | `String` | Full path of the parent directory. | +| `name` | `String` | Name of the file or directory. | +| `file_extension` | `String` | File extension, if applicable. Empty string for directories and shares. | +| `file_size` | `UInt64` | Size of the file in bytes. Zero for directories and shares. | +| `owner_sid` | `String` | SID of the file or directory owner. | +| `group_owner_sid` | `String` | SID of the primary group owner. | +| `created_time` | `Nullable(DateTime)` | Optional. Timestamp when the object was created. | +| `modified_time` | `Nullable(DateTime)` | Optional. Timestamp when the object was last modified. | +| `accessed_time` | `Nullable(DateTime)` | Optional. Timestamp when the object was last accessed. | +| `scan_status` | `Enum8('SUCCESS', 'ERROR')` | Whether the object was scanned successfully. | +| `error_message` | `String` | Error detail if `scan_status` is `ERROR`. Empty string on success. | +| `attributes` | `Array(Enum8('DIRECTORY', 'READONLY', 'HIDDEN', 'SYSTEM', 'ARCHIVE', 'COMPRESSED', 'ENCRYPTED'))` | Windows file attributes applied to the object. | +| `inheritance_flags` | `UInt16` | Bitmask representing ACL inheritance settings on the object. | +| `is_protected` | `Nullable(Bool)` | Optional. Whether the object's ACL is protected from inheritance. | +| `is_world_readable` | `Nullable(Bool)` | Optional. Whether any well-known open SID (for example, Everyone) has read access. | +| `is_world_writable` | `Nullable(Bool)` | Optional. Whether any well-known open SID has write access. | +| `is_admin_only` | `Nullable(Bool)` | Optional. Whether access is restricted to administrative accounts only. | +| `has_explicit_deny` | `Nullable(Bool)` | Optional. Whether the object has at least one explicit deny ACE. | +| `permission_count` | `UInt16` | Total number of ACEs on the object. | +| `unique_trustees_count` | `UInt16` | Number of distinct trustees with permissions on the object. | +| `permission_flags` | `UInt16` | Bitmask summarizing the permission state of the object. | +| `is_complete` | `Bool` | Whether the scan fully enumerated this object's permissions before the scan completed. | +| `hard_delete` | `Bool` | Internal flag used by `ReplacingMergeTree` to exclude deleted rows. Rows where `hard_delete = 1` are suppressed at query time when querying with `FINAL`. | + +**Relations** + +| Related table | Join column | Description | +|---------------|-------------|-------------| +| `cifs_permission` | `host`, `share_name`, `path` | Resolves NTFS permissions assigned to this file or directory. | +| `cifs_sensitive_data` | `host`, `share_name`, `path` | Resolves sensitive data findings for this file. | + +--- + +### cifs_permission + +Stores NTFS ACEs (access control entries) for files and directories — one row per trustee per path. + +| Column | Type | Description | +|--------|------|-------------| +| `trustee_sid` | `String` | SID of the user or group that this ACE grants or denies access to. | +| `host` | `String` | Hostname of the file server. | +| `share_name` | `String` | Name of the share containing the object. | +| `path` | `String` | Full path of the object this ACE applies to. | +| `permissions` | `Array(Enum8('FILE_READ_DATA', 'FILE_WRITE_DATA', 'FILE_APPEND_DATA', 'FILE_READ_EA', 'FILE_WRITE_EA', 'FILE_EXECUTE', 'FILE_DELETE_CHILD', 'FILE_READ_ATTRIBUTES', 'FILE_WRITE_ATTRIBUTES', 'DIR_LIST', 'DIR_ADD_FILE', 'DIR_ADD_SUB_DIR', 'DIR_DELETE_CHILD', 'DELETE', 'READ_CONTROL', 'WRITE_DAC', 'WRITE_OWNER', 'GENERIC_ALL', 'GENERIC_EXECUTE', 'GENERIC_WRITE', 'GENERIC_READ'))` | Individual permission flags included in this ACE. | +| `normalized_permissions` | `FixedString(6)` | Six-character string encoding the effective permissions (for example, `RWXDMC`) for use in summary queries. | +| `access_type` | `Enum8('ALLOW', 'DENY')` | Whether this ACE allows or denies access. | +| `access_mask` | `UInt32` | Raw Windows access mask bitmask for this ACE. | +| `inheritance_flags` | `UInt16` | Bitmask describing how this ACE propagates to child objects. | +| `is_inherited` | `Bool` | Whether this ACE was inherited from a parent object rather than set explicitly. | +| `mip_label_id` | `Nullable(String)` | Optional. Microsoft GUID of the MIP sensitivity label applied to this object. | +| `mip_label_name` | `Nullable(String)` | Optional. Display name of the MIP sensitivity label applied to this object. | +| `hard_delete` | `Bool` | Internal flag used by `ReplacingMergeTree` to exclude deleted rows. | + +**Relations** + +| Related table | Join column | Description | +|---------------|-------------|-------------| +| `cifs_object` | `host`, `share_name`, `path` | Resolves file system object details for this ACE. | +| `cifs_share_permission` | `host`, `share_name` | Resolves the share-level permissions that apply in combination with this NTFS ACE. | + +--- + +### cifs_share_permission + +Stores share-level ACEs — one row per trustee per share. Share permissions apply in addition to NTFS permissions; the effective access a user has is the intersection of both. + +| Column | Type | Description | +|--------|------|-------------| +| `trustee_sid` | `String` | SID of the user or group that this share ACE grants or denies access to. | +| `host` | `String` | Hostname of the file server. | +| `share_name` | `String` | Name of the share this ACE applies to. | +| `permissions` | `Array(Enum8('FILE_READ_DATA', 'FILE_WRITE_DATA', 'FILE_APPEND_DATA', 'FILE_READ_EA', 'FILE_WRITE_EA', 'FILE_EXECUTE', 'FILE_DELETE_CHILD', 'FILE_READ_ATTRIBUTES', 'FILE_WRITE_ATTRIBUTES', 'DIR_LIST', 'DIR_ADD_FILE', 'DIR_ADD_SUB_DIR', 'DIR_DELETE_CHILD', 'DELETE', 'READ_CONTROL', 'WRITE_DAC', 'WRITE_OWNER', 'GENERIC_ALL', 'GENERIC_EXECUTE', 'GENERIC_WRITE', 'GENERIC_READ'))` | Individual permission flags included in this share ACE. | +| `normalized_permissions` | `FixedString(6)` | Six-character string encoding the effective permissions for use in summary queries. | +| `access_type` | `Enum8('ALLOW', 'DENY')` | Whether this ACE allows or denies access at the share level. | +| `access_mask` | `UInt32` | Raw Windows access mask bitmask for this share ACE. | +| `mip_label_id` | `Nullable(String)` | Optional. Microsoft GUID of the MIP sensitivity label applied to this share. | +| `mip_label_name` | `Nullable(String)` | Optional. Display name of the MIP sensitivity label applied to this share. | +| `hard_delete` | `Bool` | Internal flag used by `ReplacingMergeTree` to exclude deleted rows. | + +**Relations** + +| Related table | Join column | Description | +|---------------|-------------|-------------| +| `cifs_permission` | `host`, `share_name` | Resolves NTFS ACEs that apply within this share. | + +--- + +### cifs_sensitive_data + +Stores sensitive data classification findings — one row per taxonomy term match per file path. + +| Column | Type | Description | +|--------|------|-------------| +| `host` | `String` | Hostname of the file server. | +| `share_name` | `String` | Name of the share containing the file. | +| `path` | `String` | Full path of the file where sensitive data was detected. | +| `taxonomy_name` | `String` | Name of the taxonomy that contains the matched term (for example, `PII`). | +| `term_name` | `String` | Name of the classification term that matched (for example, `Social Security Number`). | +| `processing_time_seconds` | `Float32` | Time in seconds to classify the file. | +| `classification_method` | `Nullable(Enum8('SDK_AUTO', 'SDK_CUSTOM'))` | Optional. Whether detection used the built-in automatic classification engine (`SDK_AUTO`) or a custom classification configuration (`SDK_CUSTOM`). | +| `scan_status` | `Enum8('SUCCESS', 'ERROR')` | Whether the file was processed successfully. `SUCCESS` indicates the file was read and classified, regardless of whether sensitive data was found. `ERROR` indicates a processing failure such as a file conversion error, encryption, or unsupported format. | +| `error_message` | `Nullable(String)` | Optional. Error detail when `scan_status` is `ERROR`. Null on success. | +| `hard_delete` | `Bool` | Internal flag used by `ReplacingMergeTree` to exclude deleted rows. | + +**Relations** + +| Related table | Join column | Description | +|---------------|-------------|-------------| +| `cifs_object` | `host`, `share_name`, `path` | Resolves file system object details for this finding. | +| `cifs_sensitive_data_mip_labels` | `host`, `share_name`, `path` | Resolves MIP sensitivity label decisions applied to this file. | + +--- + +### cifs_sensitive_data_mip_labels + +Stores Microsoft Information Protection (MIP) sensitivity label decisions for files that contain sensitive data findings. Each row records the label action Access Analyzer determined for a file based on its classification results. MIP labels are sourced from an Entra ID source group configured in the same Access Analyzer instance — Access Analyzer uses that source group to resolve label definitions and apply or recommend label changes. + +:::note +This table uses `ReplacingMergeTree(decision_timestamp)` rather than `scanned_at`. The most recent decision per file (identified by `source_id`, `host`, `share_name`, and `path`) is kept at merge time. +::: + +| Column | Type | Description | +|--------|------|-------------| +| `source_id` | `UUID` | Identifier of the Entra ID source group used to resolve MIP label definitions. | +| `host` | `String` | Hostname of the file server. | +| `share_name` | `String` | Name of the share containing the file. | +| `path` | `String` | Full path of the file this label decision applies to. | +| `mip_is_protected` | `Bool` | Whether the file is currently protected by MIP encryption. | +| `taxonomy_id` | `Nullable(UUID)` | Optional. Identifier of the taxonomy that triggered this label decision. | +| `action` | `Enum8('upgrade', 'keep', 'downgrade', 'clear', 'none')` | The label action Access Analyzer determined: `upgrade` applies a higher-sensitivity label, `downgrade` applies a lower-sensitivity label, `keep` leaves the current label unchanged, `clear` removes the label, and `none` indicates no action was taken. | +| `label_id` | `Nullable(UUID)` | Optional. UUID of the MIP sensitivity label selected by the action. | +| `label_name` | `Nullable(String)` | Optional. Display name of the MIP sensitivity label selected by the action. | +| `reason` | `Nullable(String)` | Optional. Explanation of why this label action was chosen. | +| `decision_timestamp` | `DateTime` | Timestamp when Access Analyzer made this label decision. | +| `scanned_at` | `DateTime` | Timestamp when the record was written. | +| `applied_at` | `Nullable(DateTime)` | Optional. Timestamp when the label was successfully applied to the file. Null if not yet applied. | +| `apply_error` | `String` | Error message if the label application failed. Empty string when no error occurred. | +| `apply_attempts` | `UInt8` | Number of times Access Analyzer has attempted to apply this label decision. | +| `created_at` | `DateTime` | Timestamp when this record was first created. | +| `updated_at` | `DateTime` | Timestamp when this record was last updated. | + +**Relations** + +| Related table | Join column | Description | +|---------------|-------------|-------------| +| `cifs_sensitive_data` | `host`, `share_name`, `path` | Resolves the sensitive data findings that triggered this label decision. | + +--- + +## Views + +Access Analyzer creates views that simplify common queries. Use views in preference to querying base tables directly. + +| View | Base table | Description | +|------|------------|-------------| +| `cifs_object_latest` | `cifs_object` | Returns the most recent version of each file system object, using `FINAL` to suppress duplicates. | +| `cifs_permission_latest` | `cifs_permission` | Returns the most recent version of each NTFS ACE, using `FINAL` to suppress duplicates. | +| `cifs_share_permission_latest` | `cifs_share_permission` | Returns the most recent version of each share-level ACE, using `FINAL` to suppress duplicates. | +| `cifs_sensitive_data_latest` | `cifs_sensitive_data` | Returns one aggregated row per file path, combining all taxonomy and term matches for that path. The `taxonomy_names` and `term_names` columns return arrays of distinct values grouped from individual rows. | +| `cifs_sensitive_data_mip_labels_latest` | `cifs_sensitive_data_mip_labels` | Returns the most recent label decision per file, using `FINAL` to suppress duplicates. | +| `cifs_sensitive_data_mip_labels_summary` | `cifs_sensitive_data_mip_labels` | Returns a summary of label decisions grouped by host, share, action, label name, and protection status. Includes decision counts and the timestamp range of first and last decisions. | +| `cifs_effective_permissions` | `cifs_permission_latest`, `cifs_share_permission_latest` | Joins NTFS and share permissions with resolved principal identities (local users, local groups, Active Directory users, Active Directory groups, and well-known SIDs) to produce one row per principal per path. Use this view to query who has access to a given path by name rather than by SID. | +| `cifs_effective_access` | `cifs_effective_permissions` | Computes the final effective access mask for each principal per path by combining NTFS allow and deny ACEs with share-level permissions. Use this view to determine the actual access a named user or group has to a file or directory. | diff --git a/docs/accessanalyzer/2601/gettingstarted/file-servers/set-up-source-group.md b/docs/accessanalyzer/2601/gettingstarted/file-servers/set-up-source-group.md new file mode 100644 index 0000000000..2994963ece --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/file-servers/set-up-source-group.md @@ -0,0 +1,62 @@ +--- +title: "Set Up File Server Source Group" +description: "Configure a file server source group in Access Analyzer" +sidebar_position: 3 +--- + +# Set Up File Server Source Group + +**Step 1 –** Navigate to **Configuration** > **Source Groups** and click **Add Source**. The source group wizard opens. + +**Step 2 –** Select **File Server** and click **Next**. + +**Step 3 –** Enter a **Source Group Name**. + +**Step 4 –** Select a service account from the **Service Account** dropdown, or click **+** to create one inline. See [Service Accounts](../../configurations/service-accounts/overview.md) for details. + +**Step 5 –** Click **Add** under **File Servers** and enter the server name or IP address of each file server to include. Click **Done** when finished. + +**Step 6 –** Click **Test Connection** to verify connectivity. Each server displays a **Connected** or **Failed** status. Resolve any failures before proceeding. + +**Step 7 –** Click **Next**. + +**Step 8 –** Enable the scan types you want to run: + +**Access scan:** + +- Toggle **Access** to enable scanning of file permissions and access controls. +- Under **Include Shares**, select **All shares** to scan every share on the server, or **Custom selection** to specify a list of shares to include. +- Optionally, add share paths to the **Exclude Shares** field to skip specific locations. Wildcards are supported (for example, `\\fileserver\*\temp*`). +- Select **Automatically enumerate hidden shares** to include hidden shares in the scan. Use the **Exclude Hidden Shares** field to exclude specific hidden shares (for example, `ADMIN$, C$, IPC$`). +- Select **Include file-level permission data** to collect permissions at the file level in addition to folder level. +- Set **Workers** to control the number of concurrent threads used during enumeration. The default is `3`. The valid range is `1–20`. + +**Sensitive Data scan:** + +- Toggle **Sensitive Data** to enable scanning of file contents for sensitive data patterns. +- Configure share selection using the same options as the Access scan above. +- Select **Inherit from Global Settings** to use the sensitive data types configured at the system level, or disable this option to configure types for this source group specifically. +- If configuring types directly, enable each sensitive data type you want to detect and assign a classification label. +- Select **Run OCR** to scan images, screenshots, and scanned documents for sensitive text. This increases processing time. + +**Step 9 –** Under **Scanner Location**, select **System scanner** to run scans from the Access Analyzer service, or select **Custom scanner** to use a deployed scanner. See [Scanners](../../configurations/source-groups/scanners/overview.md) for details. + +**Step 10 –** Under **Scan Schedule**, select when to run the scan: + +- **Now** — Starts the scan immediately after setup completes. +- **At** — Runs the scan once at a specific date and time. +- **Advanced** — Runs the scan on a recurring schedule defined by a cron expression. + +**Step 11 –** Click **Complete Setup**. + +## What Happens Next + +Access Analyzer creates the source group and a scan for each file server you added. If you selected **Now**, the enabled scans start immediately. + +To check scan progress, navigate to **Configuration** > **Scan Executions**. + +To view results after the scan completes, see [Data Security Dashboard](../../dashboards-reports/data-security-dashboard/overview.md). + +## Edit a Source Group + +To modify an existing file server source group, navigate to **Configuration** > **Source Groups**, select the source group, and click **Edit**. The wizard reopens with your current configuration pre-populated. You can update the source group name, service account, file servers, and scan settings. diff --git a/docs/accessanalyzer/2601/gettingstarted/first-service-account.md b/docs/accessanalyzer/2601/gettingstarted/first-service-account.md deleted file mode 100644 index f58efefd6c..0000000000 --- a/docs/accessanalyzer/2601/gettingstarted/first-service-account.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Setting Up a Service Account" -description: "Create a service account to connect to data sources" -sidebar_position: 1 ---- - -# Setting Up a Service Account - -*Content coming soon.* diff --git a/docs/accessanalyzer/2601/gettingstarted/sharepoint-online-scan/sharepoint-online.md b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online-scan/sharepoint-online.md deleted file mode 100644 index 0b81d403ff..0000000000 --- a/docs/accessanalyzer/2601/gettingstarted/sharepoint-online-scan/sharepoint-online.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "SharePoint Online Source Group" -description: "Making changes to a SharePoint Online source group wizard workflow" -sidebar_position: 40 ---- - -# SharePoint Online Source Group - -*Content coming soon.* diff --git a/docs/accessanalyzer/2601/gettingstarted/sharepoint-online-scan/_category_.json b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/_category_.json similarity index 61% rename from docs/accessanalyzer/2601/gettingstarted/sharepoint-online-scan/_category_.json rename to docs/accessanalyzer/2601/gettingstarted/sharepoint-online/_category_.json index 23057cd793..a8d05dd13b 100644 --- a/docs/accessanalyzer/2601/gettingstarted/sharepoint-online-scan/_category_.json +++ b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/_category_.json @@ -1,5 +1,5 @@ { - "label": "Scanning SharePoint Online", + "label": "SharePoint Online", "position": 50, "collapsed": true, "collapsible": true diff --git a/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/reports.md b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/reports.md new file mode 100644 index 0000000000..0c969c2a49 --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/reports.md @@ -0,0 +1,17 @@ +--- +title: "Reports" +description: "Pre-built reports available for SharePoint Online source groups in Access Analyzer" +sidebar_position: 50 +--- + +# Reports + +After the first scan of a SharePoint Online source group completes, three pre-built reports become available under the Reports section. These reports help you answer key security questions about your SharePoint environment: which files carry sensitive data, how broadly content is shared, and where stale or redundant data accumulates across your sites. + +## Available reports + +| Location | Report | Description | +|----------|--------|-------------| +| Access / Shared Links Report | Shared Links Report | Shows all sharing links across your SharePoint environment, with breakdowns by sharing scope (organization, anonymous, specific people), active status, sensitive data type, and site. Use this report to identify overly broad sharing and links that expose sensitive files. | +| Content / ROT Analysis | ROT Analysis | Identifies Redundant, Obsolete, and Trivial (ROT) data across your SharePoint sites, including stale files not modified in over a year, duplicate files by content hash, and stale files containing sensitive data. Use this report to prioritize data cleanup and reduce unnecessary exposure of aging content. | +| Content / Scan Overview | Scan Overview | Summarizes the results of the most recent scan across all sites, including total site count, file count, total storage, and files with sensitive data. Use this report to confirm scan coverage and quickly identify which sites hold the most sensitive content. | diff --git a/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/scanning-options.md b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/scanning-options.md new file mode 100644 index 0000000000..6c89115485 --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/scanning-options.md @@ -0,0 +1,17 @@ +--- +title: "Available Scanning Options" +description: "Available scan types and configuration options for SharePoint Online source groups" +sidebar_position: 2 +--- + +# Available Scanning Options + +| Scan Option | Description | Available Configurations | +| --- | --- | --- | +| **SharePoint Online Access** | Scans SharePoint Online sites for permissions and access controls. The first scan runs in full; subsequent scans run differentially, collecting only changes since the last run. | Site URLs (optional — leave empty to scan all sites) | + +## Scan Configuration + +**SharePoint Online Access** + +- **Site URLs** — Leave empty to scan all sites in the tenant, or enter specific site URLs to limit the scan to a subset of your SharePoint Online environment. diff --git a/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/schema-reference.md b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/schema-reference.md new file mode 100644 index 0000000000..fa0d681ea2 --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/schema-reference.md @@ -0,0 +1,166 @@ +--- +title: "SharePoint Online Schema Reference" +sidebar_position: 40 +--- + +# SharePoint Online Schema Reference + +Access Analyzer stores SharePoint Online scan data in the `access_analyzer` ClickHouse database. The tables below are created when you set up a SharePoint Online source group and run a scan. Use this reference when querying scan data directly or integrating Access Analyzer data with external tools. + +:::note +All tables use the `ReplacingMergeTree` engine. Duplicate rows with the same primary key are deduplicated at merge time. Query the `_latest` views to return only the most recent version of each record. +::: + +## Metadata columns + +All tables include the following columns populated by Access Analyzer during each scan: + +| Column | Type | Description | +|--------|------|-------------| +| `scan_id` | `String` | Identifier of the source group that produced this record. | +| `scan_execution_id` | `String` | Identifier of the specific scan run. | +| `scanned_at` | `DateTime` | Timestamp when the record was written. | + +--- + +## Tables + +### sharepoint_online_objects + +Stores one row per scanned SharePoint item — sites, lists, document libraries, and list items (files and folders). + +| Column | Type | Description | +|--------|------|-------------| +| `site_hostname` | `String` | Hostname of the SharePoint site collection (for example, `contoso.sharepoint.com`). | +| `site_id` | `String` | SharePoint identifier of the site collection. | +| `item_id` | `String` | Unique identifier of the item within the site. | +| `site_url` | `String` | Absolute URL of the site collection. | +| `drive_id` | `String` | Microsoft Graph drive identifier for the document library that contains this item. Empty for sites and lists that do not have a drive. | +| `drive_item_id` | `String` | Microsoft Graph drive item identifier. Empty for items that are not drive items. | +| `item_type` | `Enum8` | Type of SharePoint item. Values: `SITE`, `LIST`, `LIBRARY`, `LIST_ITEM`. | +| `name` | `String` | Display name of the item. | +| `file_extension` | `String` | File extension, including the leading period (for example, `.docx`). Empty for non-file items. | +| `relative_url` | `String` | Server-relative URL path of the item. | +| `file_size` | `Nullable(Int64)` | Optional. File size in bytes. Null for items that are not files. | +| `created_time` | `DateTime` | Timestamp when the item was created in SharePoint. | +| `created_by_id` | `String` | SharePoint user identifier of the user who created the item. | +| `created_by_email` | `String` | Email address of the user who created the item. | +| `modified_time` | `DateTime` | Timestamp of the most recent modification. | +| `modified_by_id` | `String` | SharePoint user identifier of the user who last modified the item. | +| `modified_by_email` | `String` | Email address of the user who last modified the item. | +| `parent_item_id` | `String` | `item_id` of the parent item. Empty for top-level sites. | +| `scan_status` | `String` | Result of scanning this item. Typical values: `SUCCESS`, `ERROR`. | +| `error_message` | `String` | Error detail when `scan_status` is `ERROR`. Empty on success. | +| `is_complete` | `Boolean` | Indicates whether the scan wrote all expected records for this item. Used internally to support scan resume. | + +**Primary key:** `(site_hostname, site_id, item_id)` + +**Relations** + +| Related table | Join columns | Description | +|---|---|---| +| `sharepoint_online_permissions` | `site_hostname`, `site_id`, `item_id` | All permissions assigned to this item. | +| `sharepoint_online_shared_links` | `site_hostname`, `site_id`, `item_id` | All sharing links created for this item. | +| `sharepoint_online_sensitive_data` | `drive_id`, `drive_item_id` | Classification results for this item. Only populated for drive items. | + +--- + +### sharepoint_online_permissions + +Stores one row per permission assignment. Each row represents a single principal (user or group) having a specific permission on a specific item. + +| Column | Type | Description | +|--------|------|-------------| +| `site_hostname` | `String` | Hostname of the site collection that contains the item. | +| `site_id` | `String` | SharePoint identifier of the site collection. | +| `item_id` | `String` | Identifier of the item this permission applies to. | +| `permission_id` | `String` | SharePoint identifier of the permission entry. | +| `share_id` | `String` | Identifier of the sharing link that granted this permission. Empty for direct permissions. | +| `principal_id` | `String` | Identifier of the user or group that holds the permission. | +| `principal_type` | `Enum8` | Type of the principal. Values: `USER`, `GROUP`, `SITE_USER`, `SITE_GROUP`. | +| `principal_name` | `String` | Display name of the principal. | +| `principal_email` | `String` | Email address of the principal. Empty for groups that do not have an email address. | +| `permission_type` | `Enum8` | How the permission was granted. Values: `DIRECT` (assigned directly to the item), `SHARED` (granted through a sharing link). | +| `permission_levels` | `Array(Enum8)` | Named permission levels assigned to the principal. Values: `OWNER`, `READ`, `WRITE`. | +| `effective_base_permissions` | `Array(Enum8)` | Full set of granular SharePoint base permissions the principal holds. Values include `VIEW_LIST_ITEMS`, `ADD_LIST_ITEMS`, `EDIT_LIST_ITEMS`, `DELETE_LIST_ITEMS`, `MANAGE_LISTS`, `MANAGE_PERMISSIONS`, `MANAGE_WEB`, and others as defined by the SharePoint permission model. | +| `normalized_permissions` | `FixedString(5)` | Compact bitmask representation of the permission levels. Used internally for permission comparison. | +| `parent_site_id` | `String` | Identifier of the site collection from which this permission is inherited. Empty for permissions that are not inherited. | +| `parent_item_id` | `String` | `item_id` of the item from which this permission is inherited. Empty for permissions assigned directly to this item. | +| `is_site_admin` | `Bool` | `true` if the principal is a site collection administrator. | +| `is_external_user` | `Bool` | `true` if the principal is a guest or external user. | +| `mip_label_id` | `Nullable(String)` | Optional. Microsoft GUID of the Microsoft Information Protection sensitivity label applied to the SharePoint item at the time of the scan. | +| `mip_label_name` | `Nullable(String)` | Optional. Display name of the sensitivity label identified by `mip_label_id`. | + +**Primary key:** `(site_hostname, site_id, item_id, permission_id, principal_id)` + +**Relations** + +| Related table | Join columns | Description | +|---|---|---| +| `sharepoint_online_objects` | `site_hostname`, `site_id`, `item_id` | The item this permission applies to. | +| `sharepoint_online_shared_links` | `site_hostname`, `site_id`, `item_id`, `share_id` | The sharing link that granted this permission, when `permission_type` is `SHARED`. | + +--- + +### sharepoint_online_shared_links + +Stores one row per sharing link. A sharing link may grant access to one or more principals; the corresponding permission rows appear in `sharepoint_online_permissions`. + +| Column | Type | Description | +|--------|------|-------------| +| `site_hostname` | `String` | Hostname of the site collection that contains the item. | +| `site_id` | `String` | SharePoint identifier of the site collection. | +| `item_id` | `String` | Identifier of the item this link points to. | +| `permission_id` | `String` | SharePoint permission identifier associated with this link. | +| `share_id` | `String` | Unique identifier of the sharing link. | +| `link_type` | `Enum8` | Access level granted by the link. Values: `VIEW`, `EDIT`, `EMBED`, `REVIEW`. | +| `link_url` | `String` | Full URL of the sharing link. | +| `link_scope` | `Enum8` | Audience the link is accessible to. Values: `ANONYMOUS` (anyone with the link), `ORGANIZATION` (anyone in the organization), `USERS` (specific users only). | +| `expires_on` | `DateTime` | Expiration timestamp of the link. A zero value indicates the link does not expire. | +| `is_password_protected` | `Bool` | `true` if the link requires a password to access. | +| `prevent_download` | `Bool` | `true` if the link prevents recipients from downloading the file. | + +**Primary key:** `(site_hostname, site_id, item_id, permission_id, share_id)` + +**Relations** + +| Related table | Join columns | Description | +|---|---|---| +| `sharepoint_online_objects` | `site_hostname`, `site_id`, `item_id` | The item this link provides access to. | +| `sharepoint_online_permissions` | `site_hostname`, `site_id`, `item_id`, `share_id` | Permissions granted through this link. | + +--- + +### sharepoint_online_sensitive_data + +Stores classification results from the sensitive data scan option. Each row represents one taxonomy term matched in a drive item. Multiple rows may exist for the same item when the item matches terms from multiple taxonomies. + +| Column | Type | Description | +|--------|------|-------------| +| `drive_id` | `String` | Microsoft Graph drive identifier of the document library that contains the item. | +| `drive_item_id` | `String` | Microsoft Graph drive item identifier of the classified file. | +| `taxonomy_name` | `String` | Name of the classification taxonomy (for example, `PII`, `Financial Records`). | +| `term_name` | `String` | Name of the specific classification term within the taxonomy (for example, `Credit Card Number`, `Social Security Number`). | +| `processing_time_seconds` | `Float32` | Time in seconds that the classification engine spent processing this item. | +| `classification_method` | `Nullable(Enum8)` | Optional. Method used to classify this item. Values: `SDK_AUTO` (automatic classification by the built-in engine), `SDK_CUSTOM` (classification using custom rules). | + +**Primary key:** `(drive_id, drive_item_id, taxonomy_name, term_name)` + +**Relations** + +| Related table | Join columns | Description | +|---|---|---| +| `sharepoint_online_objects` | `drive_id`, `drive_item_id` | The scanned item that produced these classification results. | + +--- + +## Views + +Access Analyzer creates views that simplify common queries. Use views in preference to querying base tables directly. + +| View | Base table | Description | +|------|------------|-------------| +| `sharepoint_online_objects_latest` | `sharepoint_online_objects` | Returns only the most recent version of each object record, deduplicated by `(site_hostname, site_id, item_id)`. | +| `sharepoint_online_permissions_latest` | `sharepoint_online_permissions` | Returns only the most recent version of each permission record, deduplicated by `(site_hostname, site_id, item_id, permission_id, principal_id)`. | +| `sharepoint_online_shared_links_latest` | `sharepoint_online_shared_links` | Returns only the most recent version of each sharing link record, deduplicated by `(site_hostname, site_id, item_id, permission_id, share_id)`. | +| `sharepoint_online_sensitive_data_latest` | `sharepoint_online_sensitive_data` | Returns one aggregated row per drive item, with `taxonomy_names` and `term_names` as arrays collecting all matched taxonomy and term names. Deduplicated by `(drive_id, drive_item_id)`. | diff --git a/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/set-up-source-group.md b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/set-up-source-group.md new file mode 100644 index 0000000000..b1c1d266c4 --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/set-up-source-group.md @@ -0,0 +1,49 @@ +--- +title: "Set Up SharePoint Online Source Group" +description: "Configure a SharePoint Online source group in Access Analyzer" +sidebar_position: 3 +--- + +# Set Up SharePoint Online Source Group + +**Step 1 –** Navigate to **Configuration** > **Source Groups** and click **Add Source**. The source group wizard opens. + +**Step 2 –** Select **SharePoint Online** and click **Next**. + +**Step 3 –** Enter a **Source Group Name**. + +**Step 4 –** Select a service account from the **Service Account** dropdown, or click **+** to create one inline. SharePoint Online requires a **Client ID and Certificate** service account type. See [Service Accounts](../../configurations/service-accounts/overview.md) for details. + +**Step 5 –** Enter the **Tenant ID** for your Microsoft Entra ID directory. This must be a valid UUID (for example, `550e8400-e29b-41d4-a716-446655440000`). + +**Step 6 –** Under **Certificate**, click **Generate and Download Certificate** to generate a certificate and download it to your machine. Upload this certificate to your registered Entra ID application before proceeding. See [Certificate Configuration](../../connectors/sharepoint-online/tenant-certificate-config.md) for upload steps. + +**Step 7 –** Click **Test Connection** to verify that Access Analyzer can authenticate to your SharePoint Online tenant. Resolve any failures before proceeding. + +**Step 8 –** Click **Next**. + +**Step 9 –** Under **Scanner Location**, select **System scanner** to run scans from the Access Analyzer service, or select **Custom scanner** to use a deployed scanner. See [Scanners](../../configurations/source-groups/scanners/overview.md) for details. + +**Step 10 –** Under **Scan Schedule**, select when to run the scan: + +- **Now** — Starts the scan immediately after setup completes. +- **At** — Runs the scan once at a specific date and time. +- **Advanced** — Runs the scan on a recurring schedule defined by a cron expression. + +**Step 11 –** Click **Complete Setup**. + +## What Happens Next + +Access Analyzer creates the source group and begins scanning your SharePoint Online environment. If you selected **Now**, the scan starts immediately. + +To check scan progress, navigate to **Configuration** > **Scan Executions**. + +To view results after the scan completes, see [Data Security Dashboard](../../dashboards-reports/data-security-dashboard/overview.md). + +## Edit a Source Group + +To modify an existing SharePoint Online source group, navigate to **Configuration** > **Source Groups**, select the source group, and click **Edit**. The wizard reopens with your current configuration pre-populated. You can update the source group name, service account, tenant ID, and scan schedule. + +:::note +Updating the service account replaces the certificate used to authenticate with SharePoint Online. Ensure the new service account's certificate is uploaded to your registered Entra ID application before saving. +::: diff --git a/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/sharepoint-online.md b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/sharepoint-online.md new file mode 100644 index 0000000000..347ee3f752 --- /dev/null +++ b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/sharepoint-online.md @@ -0,0 +1,33 @@ +--- +title: "SharePoint Online Scanning Overview" +description: "Overview of SharePoint Online scanning capabilities and prerequisites in Access Analyzer" +sidebar_position: 1 +--- + +# SharePoint Online Scanning Overview + +Access Analyzer scans SharePoint Online sites to map permissions, enumerate sharing links, and locate sensitive data across your tenant's document libraries and sites. It surfaces over-permissioned sites, anonymous and organization-wide sharing links, and files that contain sensitive content — giving security teams the information they need to reduce external exposure, enforce sharing policies, and meet cloud data governance requirements. + +## Prerequisites + +Before setting up a SharePoint Online source group, confirm that your environment meets the requirements below. The source group wizard connects to SharePoint Online over HTTPS using certificate-based authentication, so the Access Analyzer server must be able to reach the Microsoft identity platform and an app registration must be configured in your tenant. The certificate is generated by the wizard — you'll need the application's Client ID before you begin. + +### Service Account + +Access Analyzer uses a Client ID and Certificate service account to authenticate with SharePoint Online. Only the Client ID is entered when creating the service account — the certificate is generated automatically during source group setup when you click **Generate and Download Certificate**. You then upload the certificate to your registered Entra ID application before the connection can be tested. + +See [SharePoint Online Service Account](../../configurations/service-accounts/sharepoint-online.md) to create the service account and [SharePoint Online Connector Requirements](../../connectors/sharepoint-online/overview.md) for instructions on registering the application. + +### Network Requirements + +| Protocol | Port | Destination | +| --- | --- | --- | +| HTTPS | 443 | Microsoft identity platform (`login.microsoftonline.com`) | +| HTTPS | 443 | SharePoint Online (`yourtenant.sharepoint.com`) | + +### Before You Begin + +- A registered application in your Entra ID tenant. +- The application's **Tenant ID** and **Client ID**. +- A Client ID and Certificate service account created in Access Analyzer. +- Network connectivity from the Access Analyzer server to port 443 confirmed. diff --git a/docs/accessanalyzer/2601/gettingstarted/source-group-wizard.md b/docs/accessanalyzer/2601/gettingstarted/source-group-wizard.md deleted file mode 100644 index ece698c97b..0000000000 --- a/docs/accessanalyzer/2601/gettingstarted/source-group-wizard.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Source Group Wizard" -description: "How the Source Group Wizard guides you through connecting data sources and configuring scans" -sidebar_position: 10 ---- - -# Source Group Wizard - -*Content coming soon.* diff --git a/docs/accessanalyzer/2601/overview/overview.md b/docs/accessanalyzer/2601/overview/overview.md new file mode 100644 index 0000000000..2c2b36a077 --- /dev/null +++ b/docs/accessanalyzer/2601/overview/overview.md @@ -0,0 +1,100 @@ +--- +title: "Overview" +description: "Product overview and architecture of Netwrix Access Analyzer" +sidebar_position: 10 +--- + +# Overview + +## Product Overview + +Netwrix Access Analyzer is an on-premises Data Security Posture Management (DSPM) platform that helps security and compliance teams discover where sensitive data lives, who has access to it, and where access risks exist across their environment. + +Organizations face a persistent challenge: sensitive data accumulates across file servers, cloud platforms, and identity systems faster than security teams can track it. Permissions expand over time, inheritance gets broken, and stale data sits untouched for years — all without anyone knowing. Access Analyzer addresses this by scanning your data sources and identity providers continuously, classifying what it finds, and surfacing the results in dashboards and reports your team can act on. + +Access Analyzer connects to the following source types: + +- **File servers** — Scans SMB/CIFS file shares for permissions, folder-level ACLs, file ownership, and sensitive data content +- **SharePoint Online** — Scans SharePoint sites for permissions, sharing links, and sensitive data across document libraries +- **Active Directory** — Syncs users, groups, group memberships, and security risks from on-premises AD domains +- **Entra ID** — Syncs Microsoft Information Protection (MIP) sensitivity labels from your Microsoft 365 tenant + +After each scan, results are stored in a high-performance analytics database and made available through embedded Metabase dashboards and reports. Security teams can filter by domain, file server, site, or classification type, and drill into specific findings without writing queries. + +## Architecture Overview + +Access Analyzer runs entirely within your Kubernetes cluster. All components — the web application, API server, analytics database, and connector jobs — deploy to a single `access-analyzer` namespace. No data leaves your infrastructure. + +The platform uses a scan-as-job model: when a scan is triggered, the Connector API creates an ephemeral Kubernetes Job for the connector type (CIFS, SharePoint, Active Directory, or Entra ID). The job runs, connects to the external source, collects data, and streams results to the data ingestion service, which bulk-inserts them into ClickHouse. When the job completes, it posts a webhook back to the Core API to finalize the scan execution record. + +```mermaid +graph TB + Browser(["Browser"]) + + subgraph K8s["Kubernetes — access-analyzer namespace"] + Webapp["Web App\n(React)"] + CoreAPI["Core API\n(Rails + Sidekiq)"] + ConnAPI["Connector API\n(Go)"] + DI["Data Ingestion\n(Python)"] + MB["Metabase\n(Embedded Analytics)"] + + Redis[("Redis\nJob queue")] + PG[("PostgreSQL\nApp data")] + CH[("ClickHouse\nScan results")] + + subgraph Jobs["Connector Jobs — ephemeral Kubernetes Jobs"] + J1["CIFS Connector"] + J2["SharePoint Connector"] + J3["Active Directory Connector"] + J4["Entra ID Connector"] + end + end + + subgraph Ext["External Sources"] + FS["File Servers\nSMB · port 445"] + SP["SharePoint Online\nHTTPS · port 443"] + AD["Active Directory\nLDAP · port 389"] + EID["Entra ID\nHTTPS · port 443"] + end + + Browser -->|HTTPS| Webapp + Webapp -->|REST API| CoreAPI + Webapp -->|Embedded SDK + JWT SSO| MB + CoreAPI --> PG + CoreAPI --> Redis + CoreAPI -->|HTTP| ConnAPI + ConnAPI -->|Kubernetes Job API| Jobs + J1 -->|SMB| FS + J2 -->|Graph API| SP + J3 -->|LDAP| AD + J4 -->|Graph API| EID + J1 --> DI + J2 --> DI + J3 --> DI + J4 --> DI + DI -->|Bulk insert| CH + MB -->|JDBC| PG + MB -->|JDBC| CH +``` + +### Components + +**Web App** — React single-page application served from the cluster. Handles scan management, source configuration, results browsing, and embeds Metabase dashboards via the Metabase SDK using JWT-based single sign-on. + +**Core API** — Rails 8 application that exposes the REST API used by the web app. Manages application state in PostgreSQL, queues background jobs through Sidekiq and Redis, and coordinates scan execution by delegating to the Connector API. + +**Connector API** — Go service that translates scan requests from the Core API into Kubernetes Job definitions. It creates connector Jobs, monitors their completion, and posts results back to the Core API via webhook. + +**Connector Jobs** — Ephemeral Kubernetes Jobs that run the actual scan work. Each connector type (CIFS, SharePoint, Active Directory, Entra ID) is a containerized Python handler. Jobs connect directly to their target source, collect data, and stream rows to the Data Ingestion service in batches. Jobs are created on demand and cleaned up after completion. + +**Data Ingestion** — Python service that receives batched rows from connector jobs and bulk-inserts them into ClickHouse. Provides write isolation — connectors never write to ClickHouse directly. + +**Metabase** — Embedded analytics platform pre-configured with Access Analyzer dashboards and reports. Connects to both PostgreSQL and ClickHouse via JDBC. Users access Metabase through the web app with no separate login required. + +### Data Stores + +| Store | Purpose | +|-------|---------| +| **PostgreSQL** | Application data: users, sources, scans, scan executions, service accounts, configuration | +| **ClickHouse** | Scan results: file objects, permissions, ACLs, group memberships, sensitive data findings | +| **Redis** | Sidekiq job queue and session cache for the Core API | diff --git a/kb_allowlist.json b/kb_allowlist.json index 322f46e175..2c58c3cb4d 100644 --- a/kb_allowlist.json +++ b/kb_allowlist.json @@ -3,9 +3,9 @@ "current" ], "accessanalyzer": [ - "2601", "11.6", - "12.0" + "12.0", + "2601" ], "accessinformationcenter": [ "11.6", From 6c77906bfdbfb204fe791b8289eac309b8c1194e Mon Sep 17 00:00:00 2001 From: Farrah Gamboa Date: Mon, 13 Apr 2026 12:08:40 -0400 Subject: [PATCH 22/62] AA26: System logs docs, scanner/scope fixes, remove stale pages - Add System Logs documentation (viewing, filtering, downloading, and common troubleshooting scenarios) - Rename File Server scanner entry to "all supported file system types" instead of "Windows File Servers" to reflect actual connector scope - Remove Notifications configuration page - Remove Active Directory Dashboard, Data Security Dashboard, and Analyzing Data pages; clean up cross-references in three set-up guides Generated with AI Co-Authored-By: Claude Code --- .../2601/configurations/logs.md | 103 +++++++++++++++++- .../2601/configurations/notifications.md | 9 -- .../source-groups/scanners/overview.md | 4 +- .../_category_.json | 6 - .../active-directory-dashboard/overview.md | 9 -- .../data-security-dashboard/_category_.json | 6 - .../data-security-dashboard/activity.md | 9 -- .../data-security-dashboard/overview.md | 9 -- .../how-to-analyze-the-data.md | 9 -- .../active-directory/set-up-source-group.md | 2 - .../file-servers/set-up-source-group.md | 2 - .../sharepoint-online/set-up-source-group.md | 2 - 12 files changed, 103 insertions(+), 67 deletions(-) delete mode 100644 docs/accessanalyzer/2601/configurations/notifications.md delete mode 100644 docs/accessanalyzer/2601/dashboards-reports/active-directory-dashboard/_category_.json delete mode 100644 docs/accessanalyzer/2601/dashboards-reports/active-directory-dashboard/overview.md delete mode 100644 docs/accessanalyzer/2601/dashboards-reports/data-security-dashboard/_category_.json delete mode 100644 docs/accessanalyzer/2601/dashboards-reports/data-security-dashboard/activity.md delete mode 100644 docs/accessanalyzer/2601/dashboards-reports/data-security-dashboard/overview.md delete mode 100644 docs/accessanalyzer/2601/dashboards-reports/how-to-analyze-the-data.md diff --git a/docs/accessanalyzer/2601/configurations/logs.md b/docs/accessanalyzer/2601/configurations/logs.md index 88b30332d1..fe3890fab4 100644 --- a/docs/accessanalyzer/2601/configurations/logs.md +++ b/docs/accessanalyzer/2601/configurations/logs.md @@ -1,9 +1,108 @@ --- title: "System Logs" -description: "Viewing system logs in Access Analyzer" +description: "Viewing, filtering, and downloading system logs in Access Analyzer" sidebar_position: 90 --- # System Logs -*Content coming soon.* +The System Logs page displays application-wide log entries generated by Access Analyzer services. Use it to monitor activity, investigate scan failures, and collect diagnostic information for support. + +Navigate to **Configuration** > **System Logs** to open the page. + +## Log entry fields + +Each log entry contains the following fields. + +| Field | Description | +| --- | --- | +| **Timestamp** | The date and time the log entry was generated. | +| **Level** | The severity of the entry: **Error**, **Warn**, **Info**, or **Debug**. | +| **Component** | The internal service that generated the entry (for example, `core-api`, `connector-api`, or `scanner`). Displays **—** if not available. | +| **Source** | The data source associated with the entry, if any. Displays **—** for entries not tied to a specific source. | +| **Message** | The log message text. Hover over a truncated message to see the full text. | + +## Filter logs + +The toolbar above the log table provides five independent filters. All active filters are applied together — only entries matching all conditions are shown. Filter state is preserved in the page URL, so you can bookmark or share a filtered view. + +**Search** + +Type in the search field to filter by message text. Results update after a short pause while you type. + +**Level** + +Select a severity level to show only entries at that level. The default shows all levels. + +| Level | Description | +| --- | --- | +| **Error** | Failures that require attention. | +| **Warn** | Conditions that may indicate a problem. | +| **Info** | General operational events. | +| **Debug** | Detailed diagnostic output. | + +**Component** + +Select one or more components to show entries from those services only. The component list is populated from services that have generated logs. + +**Source** + +Select a data source to show only log entries associated with it. The source list includes sources that have activity in the past seven days. + +**Date range** + +Use the **From** and **To** fields to restrict entries to a specific time window. Both fields are optional — set only one to filter from or until a given time. + +## Sort and paginate + +The log table is sorted by timestamp, newest first by default. Click the **Timestamp** column header to reverse the sort order. + +Use the rows-per-page control to display 10, 25, 50, or 100 entries per page. + +## Download logs + +To export log entries for offline review or to provide to support: + +1. Apply any filters you want to include in the export. +2. Click the **Download** button in the toolbar. +3. Select **JSON** or **CSV** from the dropdown. + +The export file is named `system-logs-{timestamp}` and reflects all currently active filters. Exports are limited to 10,000 entries. + +CSV exports include the following columns: Timestamp, Level, Message, Trace ID, Span ID, and Attributes. + +## Common troubleshooting scenarios + +### Investigate a scan failure + +When a scan does not complete as expected: + +1. Set the **Source** filter to the data source the scan was running against. +2. Set the **Level** filter to **Error**. +3. Set the **Date range** to the window when the scan ran. +4. Review the **Message** column for error details. + +If no error-level entries appear, clear the **Level** filter and check for **Warn** entries that may indicate a configuration or connectivity issue. + +### Review logs for a specific time window + +1. Enter the start time in the **From** field. +2. Enter the end time in the **To** field. +3. Leave other filters clear to see all activity in that window. + +Use this approach to identify what was happening in the system around the time of an observed issue. + +### Isolate logs from a specific service + +1. Open the **Component** dropdown. +2. Select the service you want to focus on. + +Multiple components can be selected at the same time to compare activity across services. + +### Collect logs for a support case + +1. Set the **Date range** to cover the period when the issue occurred. +2. If the issue is tied to a specific data source, set the **Source** filter. +3. Click **Download** and select **JSON** to preserve full attribute metadata. + +Provide the downloaded file along with your support request. diff --git a/docs/accessanalyzer/2601/configurations/notifications.md b/docs/accessanalyzer/2601/configurations/notifications.md deleted file mode 100644 index 40327ecad5..0000000000 --- a/docs/accessanalyzer/2601/configurations/notifications.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Notifications" -description: "Configuring SMTP email notifications in Access Analyzer" -sidebar_position: 100 ---- - -# Notifications - -*Content coming soon.* diff --git a/docs/accessanalyzer/2601/configurations/source-groups/scanners/overview.md b/docs/accessanalyzer/2601/configurations/source-groups/scanners/overview.md index aa46eb4e4c..04bdb7dbcb 100644 --- a/docs/accessanalyzer/2601/configurations/source-groups/scanners/overview.md +++ b/docs/accessanalyzer/2601/configurations/source-groups/scanners/overview.md @@ -13,7 +13,7 @@ Scanners are lightweight, containerized agents used by Access Analyzer to perfor Scanners are available for the following connectors only: - **Active Directory** -- **Windows File Servers** +- **File Server** (all supported file system types) All other connectors (Entra ID, SharePoint Online) connect directly from the Access Analyzer service and do not use Scanners. @@ -25,7 +25,7 @@ Scanners run as Kubernetes Jobs — short-lived containers that are deployed on | --- | --- | --- | | **Distributed scanning** | Proxy server / Applet deployment | Kubernetes-deployed Scanner containers | | **Deployment model** | Manual, persistent agent | On-demand Kubernetes Jobs | -| **Supported targets** | All file system types | Active Directory, Windows File Servers | +| **Supported targets** | All file system types | Active Directory, all supported file system types | ## Pending Documentation diff --git a/docs/accessanalyzer/2601/dashboards-reports/active-directory-dashboard/_category_.json b/docs/accessanalyzer/2601/dashboards-reports/active-directory-dashboard/_category_.json deleted file mode 100644 index 1625f523d8..0000000000 --- a/docs/accessanalyzer/2601/dashboards-reports/active-directory-dashboard/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Active Directory Dashboard", - "position": 50, - "collapsed": true, - "collapsible": true -} diff --git a/docs/accessanalyzer/2601/dashboards-reports/active-directory-dashboard/overview.md b/docs/accessanalyzer/2601/dashboards-reports/active-directory-dashboard/overview.md deleted file mode 100644 index be8af55027..0000000000 --- a/docs/accessanalyzer/2601/dashboards-reports/active-directory-dashboard/overview.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Overview" -description: "Overview of the Active Directory Dashboard" -sidebar_position: 10 ---- - -# Overview - -*Content coming soon.* diff --git a/docs/accessanalyzer/2601/dashboards-reports/data-security-dashboard/_category_.json b/docs/accessanalyzer/2601/dashboards-reports/data-security-dashboard/_category_.json deleted file mode 100644 index 48567d27b0..0000000000 --- a/docs/accessanalyzer/2601/dashboards-reports/data-security-dashboard/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Data Security Dashboard", - "position": 40, - "collapsed": true, - "collapsible": true -} diff --git a/docs/accessanalyzer/2601/dashboards-reports/data-security-dashboard/activity.md b/docs/accessanalyzer/2601/dashboards-reports/data-security-dashboard/activity.md deleted file mode 100644 index cd6072b460..0000000000 --- a/docs/accessanalyzer/2601/dashboards-reports/data-security-dashboard/activity.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Activity" -description: "Activity view in the Data Security Dashboard" -sidebar_position: 20 ---- - -# Activity - -*Content coming soon.* diff --git a/docs/accessanalyzer/2601/dashboards-reports/data-security-dashboard/overview.md b/docs/accessanalyzer/2601/dashboards-reports/data-security-dashboard/overview.md deleted file mode 100644 index c6d4d8bd09..0000000000 --- a/docs/accessanalyzer/2601/dashboards-reports/data-security-dashboard/overview.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Overview" -description: "Overview of the Data Security Dashboard" -sidebar_position: 10 ---- - -# Overview - -*Content coming soon.* diff --git a/docs/accessanalyzer/2601/dashboards-reports/how-to-analyze-the-data.md b/docs/accessanalyzer/2601/dashboards-reports/how-to-analyze-the-data.md deleted file mode 100644 index de949167e3..0000000000 --- a/docs/accessanalyzer/2601/dashboards-reports/how-to-analyze-the-data.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Analyzing Data and Reports" -description: "Guide to analyzing data and reports in Access Analyzer" -sidebar_position: 10 ---- - -# Analyzing Data and Reports - -*Content coming soon.* diff --git a/docs/accessanalyzer/2601/gettingstarted/active-directory/set-up-source-group.md b/docs/accessanalyzer/2601/gettingstarted/active-directory/set-up-source-group.md index 571b505731..d272fa99a7 100644 --- a/docs/accessanalyzer/2601/gettingstarted/active-directory/set-up-source-group.md +++ b/docs/accessanalyzer/2601/gettingstarted/active-directory/set-up-source-group.md @@ -46,8 +46,6 @@ Access Analyzer creates the source group and a scan for each domain controller y To check scan progress, navigate to **Configuration** > **Scan Executions**. -To view results after the scan completes, see [Active Directory Dashboard](../../dashboards-reports/active-directory-dashboard/overview.md). - ## Edit a Source Group To modify an existing Active Directory source group, navigate to **Configuration** > **Source Groups**, select the source group, and click **Edit**. The wizard reopens with your current configuration pre-populated. You can update the source group name, service account, domain controllers, and scan schedule. diff --git a/docs/accessanalyzer/2601/gettingstarted/file-servers/set-up-source-group.md b/docs/accessanalyzer/2601/gettingstarted/file-servers/set-up-source-group.md index 2994963ece..22e0919415 100644 --- a/docs/accessanalyzer/2601/gettingstarted/file-servers/set-up-source-group.md +++ b/docs/accessanalyzer/2601/gettingstarted/file-servers/set-up-source-group.md @@ -55,8 +55,6 @@ Access Analyzer creates the source group and a scan for each file server you add To check scan progress, navigate to **Configuration** > **Scan Executions**. -To view results after the scan completes, see [Data Security Dashboard](../../dashboards-reports/data-security-dashboard/overview.md). - ## Edit a Source Group To modify an existing file server source group, navigate to **Configuration** > **Source Groups**, select the source group, and click **Edit**. The wizard reopens with your current configuration pre-populated. You can update the source group name, service account, file servers, and scan settings. diff --git a/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/set-up-source-group.md b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/set-up-source-group.md index b1c1d266c4..9eef25e248 100644 --- a/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/set-up-source-group.md +++ b/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/set-up-source-group.md @@ -38,8 +38,6 @@ Access Analyzer creates the source group and begins scanning your SharePoint Onl To check scan progress, navigate to **Configuration** > **Scan Executions**. -To view results after the scan completes, see [Data Security Dashboard](../../dashboards-reports/data-security-dashboard/overview.md). - ## Edit a Source Group To modify an existing SharePoint Online source group, navigate to **Configuration** > **Source Groups**, select the source group, and click **Edit**. The wizard reopens with your current configuration pre-populated. You can update the source group name, service account, tenant ID, and scan schedule. From 76eb208d6b7a4468d04102fcbadcec2f4ea4b8cb Mon Sep 17 00:00:00 2001 From: Farrah Gamboa Date: Mon, 13 Apr 2026 13:22:38 -0400 Subject: [PATCH 23/62] AA26: Add My Reports, Reports index, Users, Sensitive Data, and Identity Provider docs - My Reports: full article covering save, open, rename, delete, table reference - Reports: consolidated index of all available reports across File Server, SharePoint, and dashboards - Users: full article covering roles, local/IdP add flows, edit constraints, activate/deactivate, password reset, delete - Sensitive Data: full article covering MIP configuration, data types with included terms, OCR, label handling behavior - Identity Provider: new article covering Entra ID OIDC/SAML, generic SAML, and LDAP/AD setup with two-part structure (IdP-side prep and Access Analyzer-side prep) Generated with AI Co-Authored-By: Claude Code --- .../2601/configurations/identity-provider.md | 136 +++++++++++++++++ .../2601/configurations/sensitive-data.md | 138 +++++++++++++++++- .../2601/configurations/users.md | 131 ++++++++++++++++- .../2601/dashboards-reports/my-reports.md | 78 +++++++++- .../2601/dashboards-reports/reports.md | 76 ++++++++++ 5 files changed, 554 insertions(+), 5 deletions(-) create mode 100644 docs/accessanalyzer/2601/configurations/identity-provider.md create mode 100644 docs/accessanalyzer/2601/dashboards-reports/reports.md diff --git a/docs/accessanalyzer/2601/configurations/identity-provider.md b/docs/accessanalyzer/2601/configurations/identity-provider.md new file mode 100644 index 0000000000..adb59a9e77 --- /dev/null +++ b/docs/accessanalyzer/2601/configurations/identity-provider.md @@ -0,0 +1,136 @@ +--- +title: "Identity Provider" +description: "Configure single sign-on with an external Identity Provider in Access Analyzer" +sidebar_position: 75 +--- + +# Identity Provider + +Access Analyzer supports federation with your organization's identity system so that users can sign in with their existing corporate credentials. Authentication is handled by your identity provider; roles and permissions are managed within Access Analyzer. + +Setting up an identity provider connection is a two-part process: first you configure the integration in your identity system, then you prepare user accounts inside Access Analyzer. + +## Supported integration types + +| Type | Description | +| --- | --- | +| **Entra ID (OIDC)** | Access Analyzer redirects users to Microsoft Entra ID for authentication using OpenID Connect. | +| **Entra ID (SAML)** | Access Analyzer redirects users to Microsoft Entra ID for authentication using SAML 2.0. | +| **Generic SAML** | Access Analyzer redirects users to any SAML 2.0-compliant identity provider (Okta, ADFS, and others). | +| **LDAP / Active Directory** | Access Analyzer connects directly to your LDAP directory or Active Directory. Users enter their directory credentials on the Access Analyzer login page — no redirect occurs. | + +## Part 1: Configure your identity provider + +### Entra ID (OIDC) + +Complete the following steps in Azure Portal before connecting Access Analyzer. + +1. Open **Azure Portal** > **Entra ID** > **App registrations** > **New registration**. +2. Name the application and select **Accounts in this organizational directory only**. +3. Click **Register**. +4. Open the new registration > **Authentication** > **Add a platform** > **Web**. +5. Enter the redirect URI in the format `https:///auth/realms/dspm/broker//endpoint`, where `` is your Access Analyzer host and `` is the identifier for this connection. +6. Click **Save**. +7. Go to **API permissions** > **Add a permission** > **Microsoft Graph** > **Delegated permissions** and add `openid`, `profile`, and `email`. +8. Click **Grant admin consent**. +9. Go to **Certificates & secrets** > **New client secret**. Set an expiry that fits your rotation policy and copy the value immediately — it's only shown once. + +Collect the following values. You'll need them when Access Analyzer is connected to this application registration. + +| Value | Where to find it | +| --- | --- | +| **Tenant ID** | Azure Portal > Entra ID > Overview > Directory (tenant) ID | +| **Client ID** | App registration > Overview > Application (client) ID | +| **Client secret** | Created in step 9 above | + +### Entra ID (SAML) + +1. Open **Azure Portal** > **Entra ID** > **Enterprise applications** > **New application**. +2. Click **Create your own application**, name it, and select **Integrate any other application you don't find in the gallery**. +3. Click **Create**. +4. Open the enterprise application > **Single sign-on** > **SAML**. +5. Click **Edit** on Basic SAML Configuration and enter the **Identifier (Entity ID)** and **Reply URL (ACS URL)** for your Access Analyzer instance. +6. Click **Save**. +7. Copy the **App Federation Metadata URL** from the SAML configuration page. + +Collect the following values: + +| Value | Where to find it | +| --- | --- | +| **Tenant ID** | Azure Portal > Entra ID > Overview > Directory (tenant) ID | +| **App Federation Metadata URL** | Enterprise application > Single sign-on > SAML configuration page | + +### Generic SAML + +Register Access Analyzer as a service provider in your IdP using the **SP ACS URL** and **SP Entity ID** for your instance. After your IdP administrator completes the registration, collect the following values: + +| Value | Description | +| --- | --- | +| **SSO URL** | Your IdP's Single Sign-On endpoint | +| **Entity ID** | Your IdP's issuer/entity identifier | +| **Signing certificate** | Your IdP's SAML signing certificate in PEM format | +| **Email attribute name** | The SAML attribute your IdP uses to carry the user's email address (common values: `email`, `mail`, or `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress`) | + +### LDAP / Active Directory + +No application registration or callback URL is required for LDAP. Prepare the following before connecting. + +**Service account:** + +Create a dedicated, read-only service account in your directory with read access to the user base DN. For Active Directory, the account needs **Read** permission on the user OU. No write access or special group membership is required. + +**Network access:** + +The Access Analyzer cluster must be able to reach your LDAP server on the configured port (389 for LDAP, 636 for LDAPS). Confirm that this traffic is permitted from the Access Analyzer cluster's egress IP range. + +:::warning +Plain LDAP (`ldap://`) transmits credentials in cleartext. Use `ldaps://` (port 636) for production deployments. +::: + +Collect the following values: + +| Value | Description | +| --- | --- | +| **LDAP server URL** | Including protocol and port — for example, `ldaps://corp.example.com:636` | +| **Service account DN** | The distinguished name of the read-only service account | +| **Service account password** | — | +| **Users base DN** | The path where user accounts are stored — for example, `ou=users,dc=example,dc=com` | +| **Email attribute name** | The LDAP attribute that holds the user's email address (usually `mail`) | +| **Directory type** | Active Directory or generic LDAP | + +## Part 2: Prepare Access Analyzer + +### Pre-provision user accounts + +Before a user can sign in through the identity provider, their account must exist in Access Analyzer. The application authenticates them against your IdP successfully but denies access if no matching account has been created. + +:::note +The email address entered during pre-provisioning must exactly match the address sent by the IdP or stored in the LDAP `mail` attribute, including case. A mismatch causes sign-in to fail. +::: + +1. Navigate to **Configuration** > **Users**. +2. Click **Add User**. +3. Enter the user's **Name** and **Email** address. +4. Select a **Role**: **Administrator** or **Viewer**. +5. Click **Create User**. + +No password is required for pre-provisioned accounts. For details on managing users, see [Users](users.md). + +## How sign-in works after IdP is configured + +When identity provider integration is active, the Access Analyzer login page redirects users to your IdP (for OIDC and SAML) or presents a credential form that validates against your directory (for LDAP). + +On first sign-in, Access Analyzer matches the email address from the IdP token or LDAP directory to the pre-provisioned account and permanently links the IdP identity to that account. On all subsequent sign-ins, the user's unique IdP identifier is used directly. + +Sessions are valid for up to 8 hours from sign-in and expire after 4 hours of inactivity. + +## Constraints + +| Item | Detail | +| --- | --- | +| **Pre-provisioning required** | Users must have an account in Access Analyzer before their first sign-in. | +| **Email must match exactly** | The email entered during pre-provisioning must match what the IdP or LDAP directory sends, including case. | +| **Roles managed in Access Analyzer** | Roles and permissions are set in Access Analyzer, not in your IdP or directory. | +| **Local accounts coexist** | The administrator account created at deployment remains a local account and continues to sign in with a password. | +| **Password reset unavailable for federated accounts** | The **Reset Password** action in the Users page is available for local accounts only. Federated users manage their credentials through your IdP. | +| **Name and email locked after first sign-in** | Once a user has signed in at least once, their name and email are set from the IdP token and can't be changed in the Access Analyzer UI. Update them in your IdP instead. | diff --git a/docs/accessanalyzer/2601/configurations/sensitive-data.md b/docs/accessanalyzer/2601/configurations/sensitive-data.md index cb72b8ca1f..9ebdc86755 100644 --- a/docs/accessanalyzer/2601/configurations/sensitive-data.md +++ b/docs/accessanalyzer/2601/configurations/sensitive-data.md @@ -6,6 +6,140 @@ sidebar_position: 30 # Sensitive Data -Sensitive data configuration controls how Access Analyzer identifies and classifies sensitive content during scans. Settings apply globally across all source groups that include sensitive data scanning. +The Sensitive Data configuration page defines which types of sensitive content Access Analyzer identifies during scans, whether to run optical character recognition (OCR) on images, and how Microsoft Information Protection (MIP) sensitivity labels are applied to matching files. These settings apply globally and serve as the default for all sensitive data scans. -Configuration options include classification criteria, file type filters, and scanning depth. These settings determine what qualifies as sensitive data in scan results and how it is reported in the dashboards. +Navigate to **Configuration** > **Sensitive Data** to view and update the configuration. + +The page has two sections: + +- **Microsoft Information Protection (MIP) Configuration** — connects an Entra ID tenant so Access Analyzer can retrieve your organization's MIP sensitivity labels. +- **Sensitive Data Types** — controls which data types are active for scanning and optionally maps each type to a MIP label. + +## MIP configuration + +The MIP configuration section connects Access Analyzer to a Microsoft Entra ID tenant. When a tenant is connected, Access Analyzer retrieves the sensitivity labels defined in your organization's MIP policy and makes them available for mapping in the Sensitive Data Types table. + +### Select a tenant + +1. In the **Tenant ID** dropdown, select the Entra ID source that represents the tenant whose MIP labels you want to use. +2. Click **Save Configuration**. + +The dropdown lists all Entra ID sources configured in Access Analyzer. If no Entra ID sources appear, add one on the **Sources** page first. + +After you select a tenant, Access Analyzer retrieves the associated MIP labels. The status bar below the dropdown shows: + +| Indicator | Meaning | +| --- | --- | +| Labels loaded count | The number of MIP labels retrieved from the selected tenant. | +| Invalid mappings count | The number of data types whose previously saved label no longer exists in MIP. | +| Last synced time | How long ago the labels were last synchronized from Entra ID. | + +MIP labels sync automatically from Entra ID at regular intervals. If a label is removed from MIP after you save a mapping, the **MIP Label** column shows the old label name with a warning indicator, and the **Status** column shows **Label Missing**. Update or clear those mappings before saving. + +:::note +The label selector and status badges in the Sensitive Data Types table are disabled until you select a tenant and labels finish loading. +::: + +## Sensitive data types + +The Sensitive Data Types table lists all data types that Access Analyzer can detect. Enable a data type to include it in sensitive data scans. If MIP labels are available, you can also map each data type to a specific label so Access Analyzer applies that label to files that match the data type. + +### Data types + +| Data Type | Description | Includes | +| --- | --- | --- | +| **CCPA** | California Consumer Privacy Act | Social Security numbers, driver's licenses, payment card data, email addresses, IP addresses, personal identifiers for California and Canadian residents | +| **CMMC** | Cybersecurity Maturity Model Certification | Controlled Unclassified Information (CUI) markings, DoD distribution statements (B–F), export control warning labels | +| **Credentials** | Passwords, API keys, and authentication secrets | Private keys (RSA, DSA, EC), passwords, AWS, Azure, and Google Cloud connection strings, PGP key blocks, Kerberos tickets, Slack tokens, SSH authorized keys | +| **Financial Records** | Banking and financial account data | ABA routing numbers, IBAN, SWIFT codes, US bank account numbers | +| **GDPR** | General Data Protection Regulation | National IDs, passports, driver's licenses, and personal identifiers for EU and EEA member states (30 countries including Austria, France, Germany, Italy, Spain, and others) | +| **GDPR Restricted** | Special categories of personal data under GDPR | Health data, political opinions, racial or ethnic origin, religious beliefs, sexual orientation, trade union membership | +| **GLBA** | Gramm-Leach-Bliley Act | Payment card numbers, cardholder names, expiration dates, security codes (Visa, Mastercard, AMEX, Discover, and others), ABA routing numbers, Social Security numbers | +| **HIPAA** | Health Insurance Portability and Accountability Act | ICD-10 diagnosis codes, prescription drug names, medical record numbers, national drug codes, Medicare numbers, Social Security numbers, patient identifiers | +| **PCI DSS** | Payment Card Industry Data Security Standard | Payment card numbers, cardholder names, expiration dates, security codes (Visa, Mastercard, AMEX, Diners Club, Discover, JCB, UnionPay) | +| **PHI** | Protected Health Information | ICD-10 codes, prescription drug names, medical record numbers, country-specific healthcare IDs for 20+ countries including UK NHS numbers, Australian Medicare numbers, and EU health insurance identifiers | +| **PII** | Personally Identifiable Information | Social Security numbers, passports, driver's licenses, full names, dates of birth, home addresses, and national identity documents for 60+ countries | + +### Table columns + +| Column | Description | +| --- | --- | +| Checkbox | Enables or disables the data type for scanning. Select the header checkbox to enable or disable all types at once. | +| **Data Type** | The name of the sensitive data type. | +| **Description** | A short description of what the data type covers. | +| **MIP Label** | The MIP sensitivity label to apply when the data type is detected. Select a label from the dropdown, or select **— No Label —** to detect the data type without applying a label. Available only when a tenant is connected and labels are loaded. | +| **Status** | Reflects the current mapping state for the row. | + +### Status values + +| Status | Color | Meaning | +| --- | --- | --- | +| **No MIP Label** | Gray | No tenant is connected, or labels haven't loaded. No label can be assigned. | +| **Unmapped** | Yellow | A tenant is connected and labels are loaded, but no label is assigned to this data type. | +| **Mapped** | Green | A label is assigned and present in the connected tenant. | +| **Label Missing** | Red | A label was previously assigned but no longer exists in MIP. Update or clear the mapping. | + +### Enable data types + +1. In the Sensitive Data Types table, select the checkbox next to each data type you want to activate. + - To activate all data types at once, select the checkbox in the table header. + - To deactivate all data types at once, clear the header checkbox when all types are selected. +2. Click **Save Configuration**. + +### Assign MIP labels + +You can assign a MIP label to each enabled data type. When Access Analyzer finds a file that matches a data type, it applies the mapped label to that file according to the label handling behavior settings. + +1. Connect a tenant in the MIP Configuration section and wait for labels to load. +2. In the **MIP Label** column for a data type, select a label from the dropdown. + - Labels are grouped into **Default Labels** (Personal, Public, General, Confidential) and **Custom Labels** (labels specific to your organization). + - Select **— No Label —** to detect the data type without applying a label. +3. Repeat for each data type you want to map. +4. Click **Save Configuration**. + +:::note +Enabling a data type and assigning a label are independent. A data type with no label assigned is still detected during scans — Access Analyzer identifies matching files but doesn't apply a MIP label to them. +::: + +## OCR + +The **Run OCR to improve classification of images** option enables optical character recognition during scans. When enabled, Access Analyzer extracts text from images, screenshots, and scanned documents and applies the same classification rules to that text. + +Enabling OCR increases scan processing time. + +1. Select or clear the **Run OCR to improve classification of images** checkbox. +2. Click **Save Configuration**. + +## Label handling behavior + +The **Label Settings** drawer controls how Access Analyzer applies, updates, or removes MIP labels during scans. To open it, click **Label Settings** in the upper-right corner of the Sensitive Data Types card. + +### Options + +| Option | Default | Description | +| --- | --- | --- | +| **Clear label if no longer sensitive** | Off | When enabled, Access Analyzer removes the MIP label from a file if the file no longer matches any enabled sensitive data type in a subsequent scan. | +| **Allow overwriting existing labels** | Off | When enabled, Access Analyzer applies the mapped label even if the file already has a MIP label assigned. When disabled, Access Analyzer skips files that already have a label. | +| **Allow downgrading labels** | Off | When enabled, Access Analyzer can replace a higher-priority label with a lower-priority one. Requires **Allow overwriting existing labels** to be enabled. | + +:::warning +**Allow downgrading labels** requires **Allow overwriting existing labels** to be on. If you turn off **Allow overwriting existing labels**, the **Allow downgrading labels** option is unavailable. +::: + +To configure label handling: + +1. Click **Label Settings**. +2. Select or clear the options as needed. +3. Click **Done** to close the drawer. +4. Click **Save Configuration** to apply all pending changes. + +## Save and cancel + +The **Save Configuration** and **Cancel** buttons are inactive until you make a change. + +- **Save Configuration** — saves all pending changes, including data type selections, MIP label mappings, the OCR setting, and label handling behavior. +- **Cancel** — discards all pending changes and restores the form to the last saved state. + +:::note +If you navigate away from the page with unsaved changes, Access Analyzer displays a confirmation dialog before leaving. +::: diff --git a/docs/accessanalyzer/2601/configurations/users.md b/docs/accessanalyzer/2601/configurations/users.md index 50aa57edd1..54fbdbf010 100644 --- a/docs/accessanalyzer/2601/configurations/users.md +++ b/docs/accessanalyzer/2601/configurations/users.md @@ -6,4 +6,133 @@ sidebar_position: 70 # Users -*Content coming soon.* +The Users page lets you create and manage the accounts that have access to Netwrix Access Analyzer. Navigate to **Configuration** > **Users** to view and manage all users. + +:::note +This page is available to administrators only. +::: + +## Users list + +The users list displays all accounts in the system. Each row shows: + +| Column | Description | +| --- | --- | +| **Username** | The display name for the account. | +| **Email** | The email address used to sign in. | +| **Role** | The account's role: **Administrator** or **Viewer**. | +| **Status** | Whether the account is **Active** or **Inactive**. | +| **Last Login** | The date of the most recent successful sign-in, or **Never** if the user hasn't signed in yet. | + +Use the search field to filter by name or email. You can sort by any column. + +## Roles + +Access Analyzer has two roles: + +| Role | Access | +| --- | --- | +| **Administrator** | Full access to all features, including user management. | +| **Viewer** | Read-only access. | + +## Add a user + +The form for adding a user differs depending on whether your deployment uses an external Identity Provider (IdP) for authentication. + +### Add a user (local authentication) + +Use this procedure when Access Analyzer manages passwords directly. + +1. Click **Add User**. +2. Enter a **Name**. Names must be between 2 and 100 characters. +3. Enter an **Email** address. Email addresses must be unique across all users (case-insensitive). +4. Select a **Role**: **Administrator** or **Viewer**. The default is **Viewer**. +5. Enter a **Password** and confirm it. +6. Click **Create User**. + +Password requirements for local accounts: + +- Minimum 18 characters +- At least one uppercase letter (A–Z) +- At least one lowercase letter (a–z) +- At least one number (0–9) +- At least one special character (`!@#$%^&*(),.?":{}|<>`) +- Can't contain the user's email address +- Can't be a commonly used password + +### Add a user (Identity Provider) + +When your deployment is configured to use an external Identity Provider, you can pre-provision an account before the user's first sign-in. Access Analyzer creates the account record and links it to the user's IdP identity when they sign in for the first time. + +1. Click **Add User**. +2. Enter a **Name**. Names must be between 2 and 100 characters. +3. Enter an **Email** address. The email must match the address the user has in your IdP. +4. Select a **Role**: **Administrator** or **Viewer**. The default is **Viewer**. +5. Click **Create User**. + +No password is required. The account is ready for the user to sign in through your IdP. + +## Edit a user + +1. In the users list, click the actions menu for a user and select **Edit**. +2. Modify the fields as needed. +3. Click **Update User**. + +What you can change depends on the account type: + +| Account type | Editable fields | +| --- | --- | +| Local (password-based) | Name, Email, Role | +| Identity Provider — pre-provisioned (hasn't signed in yet) | Name, Email, Role | +| Identity Provider — provisioned (has signed in at least once) | Role only | + +Name and email are locked for provisioned IdP accounts because those values come from the IdP token. To change them, update the user's profile in your IdP. + +## Activate a user + +1. In the users list, click the actions menu for an inactive user and select **Activate**. + +The account becomes active immediately. The user can sign in and use the application according to their assigned role. + +## Deactivate a user + +1. In the users list, click the actions menu for an active user and select **Deactivate**. + +Deactivating a user revokes all of their active sessions immediately. The account record is preserved and can be reactivated later. + +:::note +You can't deactivate your own account or the last active administrator account. +::: + +## Reset a user's password + +:::note +The **Reset Password** action is available for local accounts only. It doesn't appear for accounts that authenticate through an Identity Provider. +::: + +1. In the users list, click the actions menu for a user and select **Reset Password**. + +Access Analyzer generates a password reset token for the user. The user must set a new password before they can sign in again. Reset tokens expire after 2 hours. + +## Delete a user + +1. In the users list, click the actions menu for a user and select **Delete**. +2. Confirm the deletion. + +:::warning +Deleting a user is permanent and can't be undone. +::: + +You can't delete your own account or the last active administrator account. + +## Constraints + +| Setting | Constraint | +| --- | --- | +| **Name** | 2–100 characters | +| **Email** | Must be unique across all users (case-insensitive); must be a valid email address | +| **Role** | Administrator or Viewer; defaults to Viewer | +| **Password** | Minimum 18 characters; must include uppercase, lowercase, number, and special character; can't match the user's email; can't be a commonly used password | +| **Deactivate** | Blocked for your own account and the last active administrator | +| **Delete** | Blocked for your own account and the last active administrator | +| **Reset Password** | Local accounts only; tokens expire after 2 hours | diff --git a/docs/accessanalyzer/2601/dashboards-reports/my-reports.md b/docs/accessanalyzer/2601/dashboards-reports/my-reports.md index 5b232cd88a..c0b0e171b0 100644 --- a/docs/accessanalyzer/2601/dashboards-reports/my-reports.md +++ b/docs/accessanalyzer/2601/dashboards-reports/my-reports.md @@ -1,9 +1,83 @@ --- title: "My Reports" -description: "Custom saved reports" +description: "Save, manage, and reload filtered report views in Netwrix Access Analyzer" sidebar_position: 30 --- # My Reports -*Content coming soon.* +My Reports is a personal workspace for saving filtered report views. When you configure a report with specific filters — a particular share, user, or time range — you can save that configuration as a named report and reload it later without reapplying the filters manually. + +Saved reports are private to the user who created them. Other users can't view or modify your saved reports. + +Navigate to **Reports** > **My Reports** to view your saved reports. + +## Save a report + +You can save any report that has the **Save Report** button in its toolbar. The button appears on File System and SharePoint report pages. + +1. Navigate to the report you want to save — for example, **Reports** > **File System** > **Access**. +2. Select a report type from the selector — for example, **Share Audit**. +3. Apply the filters you want to capture. +4. Click **Save Report** in the toolbar. +5. In the **Save Report** dialog, enter a name for the report. Names are required, must be unique (case-insensitive) within your saved reports, and can't exceed 100 characters. +6. Review the **Current Filters** section to confirm the active filters are correct. +7. Click **Save Report**. + +After saving, Access Analyzer redirects you to **My Reports** where the new report appears in the list. + +:::note +If no filters are applied when you click **Save Report**, the dialog indicates that no filters are active. You can still save the report, but it will open with the default unfiltered view. +::: + +## Open a saved report + +1. Navigate to **Reports** > **My Reports**. +2. In the **My Saved Reports** table, click the row for the report you want to open. + +The report opens with its saved filter configuration applied. A banner at the top of the report displays the report name and a **Back to My Reports** button. + +To return to the **My Reports** list, click **Back to My Reports** in the banner. + +## Rename a saved report + +1. Navigate to **Reports** > **My Reports**. +2. In the **Actions** column for the report you want to rename, click the actions icon (**⋮**). +3. Select **Rename**. +4. Edit the name in the inline text field. The name can't exceed 100 characters. +5. Press **Enter** or click the check icon to save the new name. Press **Escape** or click the X icon to cancel. + +## Delete a saved report + +1. Navigate to **Reports** > **My Reports**. +2. In the **Actions** column for the report you want to delete, click the actions icon (**⋮**). +3. Select **Delete**. + +:::warning +Deleting a saved report is permanent. There's no confirmation step and no undo. +::: + +## My Saved Reports table + +The **My Saved Reports** table lists all reports you've saved. + +| Column | Description | +| --- | --- | +| **Name** | The name of the saved report. Click a row to open the report. | +| **Parent Report** | The report type this was saved from — for example, **Share Audit** or **Broken Inheritance**. Displays a dash if the source can't be identified. | +| **Created** | The date the report was saved. | +| **Actions** | Opens a menu with **Rename** and **Delete** options. | + +When you haven't saved any reports yet, the table displays: + +> *You haven't saved any reports yet. Go to Access, Content, or Activity reports, apply filters, and click "Save Report" to save them here.* + +The table paginates when it contains more than 10 reports. You can display 10 or 25 rows per page. + +## Report name constraints + +| Constraint | Detail | +| --- | --- | +| **Required** | A name is required to save a report. | +| **Maximum length** | 100 characters. | +| **Uniqueness** | Names must be unique within your saved reports (case-insensitive). | diff --git a/docs/accessanalyzer/2601/dashboards-reports/reports.md b/docs/accessanalyzer/2601/dashboards-reports/reports.md new file mode 100644 index 0000000000..aae3642661 --- /dev/null +++ b/docs/accessanalyzer/2601/dashboards-reports/reports.md @@ -0,0 +1,76 @@ +--- +title: "Reports" +description: "All pre-built dashboards and reports available in Netwrix Access Analyzer" +sidebar_position: 10 +--- + +# Reports + +Netwrix Access Analyzer includes pre-built dashboards and reports that surface findings from your scans. Reports become available after the first scan of a source group completes and update each time a scan runs. + +Reports are organized by data source type and grouped by category in the navigation under **Dashboards** and **Reports**. + +## Dashboards + +| Dashboard | Description | +| --- | --- | +| **Data Security** | An overview of data security posture across all connected data sources. | +| **Active Directory** | An overview of Active Directory scan results for one or more domains. Shows inventory counts for users, groups, and group memberships alongside security risk data, including risk breakdowns by type and severity and a ranked list of the objects with the highest number of associated risks. Filter by domain to focus on a specific part of your environment. | + +## File Server reports + +For full details on these reports, see [File Server Reports](/docs/accessanalyzer/2601/gettingstarted/file-servers/reports). + +### Access + +| Report | Description | +| --- | --- | +| **Broken Inheritance** | Lists shares and folders where permission inheritance has been broken, meaning the folder's ACL no longer follows its parent. Use this report to find locations where custom permission assignments may have introduced inconsistencies or unexpected access. | +| **Domain User ACLs** | Shows share and folder permissions assigned directly to domain user accounts. Use this report to identify accounts with direct ACL entries that should be managed through groups instead. | +| **High Risk ACLs** | Identifies folders where broad trustees such as Everyone, Authenticated Users, or Domain Users appear in the access control list. Use this report to locate and remediate over-permissioned folders that expose data to wide audiences. | +| **Local Administrators** | Lists local administrator accounts and the hosts where they hold that privilege. Use this report to identify non-standard or unauthorized local administrator assignments across your file servers. | +| **Missing Full Control** | Lists folders where no trustee holds Full Control permission. Use this report to identify folders that may lack a clear owner or administrator and address potential access management gaps. | +| **Open Access** | Identifies folders and shares accessible to broad groups or where sensitive data is reachable without restriction. Use this report to prioritize remediation of the most exposed locations in your file server environment. | +| **Probable Owner** | Identifies the most likely owner for each share based on access patterns and file activity. Use this report to assign data ownership and support data governance workflows. | +| **Share Audit** | Provides a detailed breakdown of share-level attributes including scan status, last scanned date, file counts, object counts, and active users. Use this report to confirm scan coverage and review the overall state of each share. | + +### Activity + +| Report | Description | +| --- | --- | +| **Activity Investigation** | Displays file system events filtered by date range, user, path, and event type. Use this report to trace the actions of a specific user or investigate changes to a specific file or folder. | + +### Content + +| Report | Description | +| --- | --- | +| **Empty Shares** | Lists shares that contain no files. Use this report to identify shares that can be reviewed for decommissioning or consolidation. | +| **Largest Shares** | Ranks file shares by total size. Use this report to identify shares that consume the most storage and prioritize them for review or cleanup. | +| **Nested Shares** | Identifies shares that are nested inside other shares, creating multiple access paths to the same data with potentially different permissions. Use this report to find and resolve configurations that complicate permission management and access auditing. | +| **Stale Content** | Identifies files and shares that haven't been accessed within a configurable threshold. Use this report to locate data that may be a candidate for archiving, deletion, or access review. | + +### Sensitive Data + +| Report | Description | +| --- | --- | +| **Sensitive Data Activity** | Shows file system events involving files that contain sensitive data, filtered by date range, event type, user, and classification taxonomy. Use this report to identify who is reading, modifying, or deleting sensitive files and to detect potential data exfiltration or misuse. | +| **Sensitive Data Overview** | Provides a high-level summary of sensitive data scan findings across CIFS/SMB file shares, including the number of files with matches, classification terms found, and distribution by host and share. Use this report as a starting point for understanding where sensitive data lives in your file server environment. | +| **Share Audit** | Shows share-level details in the context of sensitive data findings, including which shares contain files with sensitive data matches. Use this report to understand sensitive data distribution across shares and prioritize remediation. | +| **Stale Data** | Identifies files containing sensitive data that haven't been accessed recently. Use this report to find aging sensitive content that may no longer be actively used but still carries exposure risk. | + +## SharePoint Online reports + +For full details on these reports, see [SharePoint Online Reports](/docs/accessanalyzer/2601/gettingstarted/sharepoint-online/reports). + +### Access + +| Report | Description | +| --- | --- | +| **Shared Links Report** | Shows all sharing links across your SharePoint environment, with breakdowns by sharing scope (organization, anonymous, specific people), active status, sensitive data type, and site. Use this report to identify overly broad sharing and links that expose sensitive files. | + +### Content + +| Report | Description | +| --- | --- | +| **ROT Analysis** | Identifies Redundant, Obsolete, and Trivial (ROT) data across your SharePoint sites, including stale files not modified in over a year, duplicate files by content hash, and stale files containing sensitive data. Use this report to prioritize data cleanup and reduce unnecessary exposure of aging content. | +| **Scan Overview** | Summarizes the results of the most recent scan across all sites, including total site count, file count, total storage, and files with sensitive data. Use this report to confirm scan coverage and quickly identify which sites hold the most sensitive content. | From f5578b914b336a8a98c3d42a35ea85916bfdb3a2 Mon Sep 17 00:00:00 2001 From: Farrah Gamboa Date: Mon, 13 Apr 2026 13:30:06 -0400 Subject: [PATCH 24/62] AA26: Add IdP installation article and cross-link configuration article - New install/identity-provider.md: infrastructure prerequisites by IdP type (Entra ID OIDC/SAML, generic SAML, LDAP/AD), network requirements, custom CA bundle setup, kcadm.sh connection process, verification steps, and troubleshooting table - Updated configurations/identity-provider.md: added cross-link to installation article Generated with AI Co-Authored-By: Claude Code --- .../2601/configurations/identity-provider.md | 4 + .../2601/install/identity-provider.md | 112 ++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 docs/accessanalyzer/2601/install/identity-provider.md diff --git a/docs/accessanalyzer/2601/configurations/identity-provider.md b/docs/accessanalyzer/2601/configurations/identity-provider.md index adb59a9e77..5b9d7feacc 100644 --- a/docs/accessanalyzer/2601/configurations/identity-provider.md +++ b/docs/accessanalyzer/2601/configurations/identity-provider.md @@ -10,6 +10,10 @@ Access Analyzer supports federation with your organization's identity system so Setting up an identity provider connection is a two-part process: first you configure the integration in your identity system, then you prepare user accounts inside Access Analyzer. +:::note +Before completing the steps below, confirm that the infrastructure and network requirements for your IdP type are in place. See [Configure Identity Provider](../install/identity-provider.md) in the Installation section. +::: + ## Supported integration types | Type | Description | diff --git a/docs/accessanalyzer/2601/install/identity-provider.md b/docs/accessanalyzer/2601/install/identity-provider.md new file mode 100644 index 0000000000..d52cc33531 --- /dev/null +++ b/docs/accessanalyzer/2601/install/identity-provider.md @@ -0,0 +1,112 @@ +--- +title: "Configure Identity Provider" +description: "Deployment and infrastructure requirements for Identity Provider integration in Access Analyzer" +sidebar_position: 50 +--- + +# Configure Identity Provider + +Access Analyzer uses Keycloak as its identity broker. Keycloak is deployed and configured automatically as part of the Access Analyzer installation. Identity provider (IdP) connections are set up after the cluster is running, using the Keycloak Admin CLI (`kcadm.sh`) via `kubectl exec` into the Keycloak pod. + +This article covers what to prepare at the infrastructure and network level before connecting an IdP. For what to prepare in your identity provider and inside the Access Analyzer application after the connection is made, see [Identity Provider](../configurations/identity-provider.md). + +## How Keycloak is deployed + +The installer handles Keycloak automatically: + +- The `dspm` realm is created from a pre-built configuration file during Keycloak startup +- All credentials (Keycloak admin password, database password, OIDC client secret) are generated by the `dspm-init` job before the cluster starts +- The Keycloak administration console is accessible only via `kubectl exec` into the Keycloak pod — it is not exposed through the Access Analyzer web interface + +No IdP-specific secrets or credentials are required at installation time. IdP connections are added after the cluster is healthy. + +## Infrastructure requirements by IdP type + +### Entra ID (OIDC) and Entra ID (SAML) + +No firewall changes are required. The Keycloak pod has outbound HTTPS (port 443) access to `login.microsoftonline.com` by default. + +Before connecting Entra ID, complete the app registration steps in [Identity Provider](../configurations/identity-provider.md#part-1-configure-your-identity-provider) and have the following values ready: + +| Value | Source | +| --- | --- | +| **Tenant ID** | Azure Portal > Entra ID > Overview | +| **Client ID** (OIDC only) | App registration > Overview | +| **Client secret** (OIDC only) | App registration > Certificates & secrets | +| **App Federation Metadata URL** (SAML only) | Enterprise application > Single sign-on | + +### Generic SAML + +No firewall changes are required for SAML IdPs reachable over the public internet. The Keycloak pod has outbound HTTPS (port 443) access by default. + +Have the following values ready from your IdP administrator: + +| Value | Description | +| --- | --- | +| **SSO URL** | Your IdP's Single Sign-On endpoint | +| **Entity ID** | Your IdP's issuer/entity identifier | +| **Signing certificate** | PEM format, without `-----BEGIN CERTIFICATE-----` headers | +| **Email attribute name** | The SAML attribute your IdP uses to carry the user's email address | + +### LDAP / Active Directory + +LDAP federation requires network access from the Access Analyzer cluster to your LDAP server. Confirm the following with your network team before configuring the connection. + +**Required network access:** + +| Source | Destination | Port | Protocol | +| --- | --- | --- | --- | +| Access Analyzer cluster egress IP | LDAP server hostname or IP | 636 | TCP (LDAPS) | +| Access Analyzer cluster egress IP | LDAP server hostname or IP | 389 | TCP (plain LDAP) | + +:::warning +Plain LDAP (`ldap://`, port 389) transmits credentials in cleartext. Use LDAPS (`ldaps://`, port 636) for production deployments. +::: + +Have the following values ready: + +| Value | Description | +| --- | --- | +| **LDAP server URL** | Including protocol and port — for example, `ldaps://corp.example.com:636` | +| **Service account DN** | A read-only account with access to the user base DN | +| **Service account password** | — | +| **Users base DN** | For example, `ou=users,dc=example,dc=com` | +| **Email attribute name** | Usually `mail`; confirm with your directory administrator | +| **Directory type** | Active Directory or generic LDAP | + +## Custom CA certificates + +If your LDAP server or SAML IdP uses a TLS certificate issued by a private or internal certificate authority, the Keycloak pod must trust that CA. Set the `customCaBundle` option in the `infra` chart values before deploying, or redeploy with it set if the cluster is already running. This mounts the CA bundle into the Keycloak pod so it can validate TLS connections to your IdP or LDAP server. + +## Connect the IdP + +Once the infrastructure prerequisites above are in place, the IdP connection is configured using `kcadm.sh` scripts via `kubectl exec` into the Keycloak pod. The scripts: + +1. Authenticate to the Keycloak Admin API inside the pod +2. Create the IdP instance (OIDC/SAML identity provider or LDAP user federation component) +3. Add the email attribute mapper required for Access Analyzer to match users on first sign-in + +## Verify the connection + +After the IdP connection is configured, test with a real user account: + +1. Open a private browser window and navigate to the Access Analyzer login page. +2. Select the IdP sign-in option (or enter LDAP credentials directly, for LDAP federation) and complete authentication. +3. Confirm that the user can access Access Analyzer with the correct role assigned. + +If sign-in fails after successful authentication with your IdP, the most common cause is that the user's account hasn't been pre-provisioned in Access Analyzer. See [Pre-provision user accounts](../configurations/identity-provider.md#pre-provision-user-accounts). + +## Troubleshooting + +| Symptom | Likely cause | Resolution | +| --- | --- | --- | +| Login succeeds at the IdP but Access Analyzer shows "access denied" | User account not pre-provisioned | Create the user account under **Configuration** > **Users** | +| Login fails with "invalid redirect URI" | Redirect URI not registered in the Azure App Registration or Enterprise Application | Add `https:///auth/realms/dspm/broker//endpoint` to the app registration | +| LDAP bind fails | Network policy blocking port 636 or 389, or incorrect service account credentials | Confirm firewall rules allow traffic from the cluster to the LDAP server; verify the service account DN and password | +| SAML signature validation fails | Wrong signing certificate used during configuration | Re-export the signing certificate from your IdP and reconfigure the connection | + +## Next steps + +After verifying the IdP connection: + +- [Identity Provider](../configurations/identity-provider.md) — pre-provision user accounts in Access Analyzer so users can sign in From 1873c3945da53c3257279397cd276488d7225b5c Mon Sep 17 00:00:00 2001 From: Farrah Gamboa Date: Mon, 13 Apr 2026 13:43:30 -0400 Subject: [PATCH 25/62] Rewrite install/identity-provider.md with full kcadm.sh procedures Replaces vague bullet-point steps with complete kubectl/kcadm.sh commands for all four IdP types (Entra OIDC, Entra SAML, Generic SAML, LDAP/AD). Adds operator scope note, before-you-begin checklist, shared authentication step, verification commands, and next-steps cross-link to the config article. Generated with AI Co-Authored-By: Claude Code --- .../2601/install/identity-provider.md | 357 +++++++++++++----- 1 file changed, 271 insertions(+), 86 deletions(-) diff --git a/docs/accessanalyzer/2601/install/identity-provider.md b/docs/accessanalyzer/2601/install/identity-provider.md index d52cc33531..3bd8169d41 100644 --- a/docs/accessanalyzer/2601/install/identity-provider.md +++ b/docs/accessanalyzer/2601/install/identity-provider.md @@ -1,112 +1,297 @@ --- title: "Configure Identity Provider" -description: "Deployment and infrastructure requirements for Identity Provider integration in Access Analyzer" +description: "Deployment steps for connecting an Identity Provider to Access Analyzer" sidebar_position: 50 --- # Configure Identity Provider -Access Analyzer uses Keycloak as its identity broker. Keycloak is deployed and configured automatically as part of the Access Analyzer installation. Identity provider (IdP) connections are set up after the cluster is running, using the Keycloak Admin CLI (`kcadm.sh`) via `kubectl exec` into the Keycloak pod. - -This article covers what to prepare at the infrastructure and network level before connecting an IdP. For what to prepare in your identity provider and inside the Access Analyzer application after the connection is made, see [Identity Provider](../configurations/identity-provider.md). - -## How Keycloak is deployed - -The installer handles Keycloak automatically: - -- The `dspm` realm is created from a pre-built configuration file during Keycloak startup -- All credentials (Keycloak admin password, database password, OIDC client secret) are generated by the `dspm-init` job before the cluster starts -- The Keycloak administration console is accessible only via `kubectl exec` into the Keycloak pod — it is not exposed through the Access Analyzer web interface - -No IdP-specific secrets or credentials are required at installation time. IdP connections are added after the cluster is healthy. - -## Infrastructure requirements by IdP type - -### Entra ID (OIDC) and Entra ID (SAML) - -No firewall changes are required. The Keycloak pod has outbound HTTPS (port 443) access to `login.microsoftonline.com` by default. - -Before connecting Entra ID, complete the app registration steps in [Identity Provider](../configurations/identity-provider.md#part-1-configure-your-identity-provider) and have the following values ready: - -| Value | Source | -| --- | --- | -| **Tenant ID** | Azure Portal > Entra ID > Overview | -| **Client ID** (OIDC only) | App registration > Overview | -| **Client secret** (OIDC only) | App registration > Certificates & secrets | -| **App Federation Metadata URL** (SAML only) | Enterprise application > Single sign-on | +:::note +This article is for the team performing the Access Analyzer deployment. It covers the cluster-level steps required to connect an identity provider to Keycloak. If you are an application administrator setting up user accounts after the IdP connection is in place, see [Identity Provider](../configurations/identity-provider.md). +::: -### Generic SAML +Access Analyzer uses Keycloak as its identity broker. Keycloak is deployed and configured automatically during installation. IdP connections are added after the cluster is running by running configuration scripts via `kubectl exec` into the Keycloak pod. -No firewall changes are required for SAML IdPs reachable over the public internet. The Keycloak pod has outbound HTTPS (port 443) access by default. +Configuration scripts for each IdP type are included in the Access Analyzer distribution at `scripts/configure-.sh`. A verification script is available at `scripts/verify-idp-config.sh`. -Have the following values ready from your IdP administrator: +## Before you begin -| Value | Description | -| --- | --- | -| **SSO URL** | Your IdP's Single Sign-On endpoint | -| **Entity ID** | Your IdP's issuer/entity identifier | -| **Signing certificate** | PEM format, without `-----BEGIN CERTIFICATE-----` headers | -| **Email attribute name** | The SAML attribute your IdP uses to carry the user's email address | +Confirm the following before running any configuration script: -### LDAP / Active Directory +- The Access Analyzer cluster is deployed and healthy +- You have `kubectl` access to the `access-analyzer` namespace +- The required credentials have been collected from the customer's IdP or directory administrator (see [Identity Provider — Part 1](../configurations/identity-provider.md#part-1-configure-your-identity-provider)) +- For LDAP: the Keycloak pod has network access to the LDAP server on port 636 (LDAPS) or 389 (LDAP) +- For private CA certificates: `customCaBundle` is set in the `infra` chart values and the cluster has been (re)deployed with it -LDAP federation requires network access from the Access Analyzer cluster to your LDAP server. Confirm the following with your network team before configuring the connection. +## Authenticate to the Keycloak Admin CLI -**Required network access:** +Run this step before configuring any IdP type. It authenticates the Keycloak Admin CLI inside the pod using the bootstrap credentials injected at deploy time. -| Source | Destination | Port | Protocol | -| --- | --- | --- | --- | -| Access Analyzer cluster egress IP | LDAP server hostname or IP | 636 | TCP (LDAPS) | -| Access Analyzer cluster egress IP | LDAP server hostname or IP | 389 | TCP (plain LDAP) | +```bash +kubectl exec -n access-analyzer statefulset/keycloak -- bash -c ' + /opt/keycloak/bin/kcadm.sh config credentials \ + --server http://localhost:8080/auth \ + --realm master \ + --user "$KC_BOOTSTRAP_ADMIN_USERNAME" \ + --password "$KC_BOOTSTRAP_ADMIN_PASSWORD"' +``` -:::warning -Plain LDAP (`ldap://`, port 389) transmits credentials in cleartext. Use LDAPS (`ldaps://`, port 636) for production deployments. +:::note +The bootstrap admin credentials are read from environment variables already present in the pod. Do not pass them as command-line arguments — they would appear in Kubernetes audit logs. ::: -Have the following values ready: - -| Value | Description | -| --- | --- | -| **LDAP server URL** | Including protocol and port — for example, `ldaps://corp.example.com:636` | -| **Service account DN** | A read-only account with access to the user base DN | -| **Service account password** | — | -| **Users base DN** | For example, `ou=users,dc=example,dc=com` | -| **Email attribute name** | Usually `mail`; confirm with your directory administrator | -| **Directory type** | Active Directory or generic LDAP | - -## Custom CA certificates - -If your LDAP server or SAML IdP uses a TLS certificate issued by a private or internal certificate authority, the Keycloak pod must trust that CA. Set the `customCaBundle` option in the `infra` chart values before deploying, or redeploy with it set if the cluster is already running. This mounts the CA bundle into the Keycloak pod so it can validate TLS connections to your IdP or LDAP server. - -## Connect the IdP +## Configure Entra ID (OIDC) -Once the infrastructure prerequisites above are in place, the IdP connection is configured using `kcadm.sh` scripts via `kubectl exec` into the Keycloak pod. The scripts: +**Required values:** Tenant ID, Client ID, Client secret (from the Azure App Registration) -1. Authenticate to the Keycloak Admin API inside the pod -2. Create the IdP instance (OIDC/SAML identity provider or LDAP user federation component) -3. Add the email attribute mapper required for Access Analyzer to match users on first sign-in +**Step 1 — Create the OIDC identity provider** -## Verify the connection +```bash +kubectl exec -i -n access-analyzer statefulset/keycloak -- bash </v2.0/.well-known/openid-configuration' \ + -s 'config.clientId=' \ + -s 'config.clientSecret=' \ + -s 'config.defaultScope=openid email profile' +EOF +``` + +Replace ``, ``, and `` with the values collected from the customer's Azure App Registration. Pass the client secret via stdin heredoc (as shown) to keep it out of Kubernetes audit logs. + +**Step 2 — Refresh OIDC discovery endpoints** + +Keycloak does not always populate the authorization, token, and JWKS URLs from the discovery endpoint at creation time. Run this step to explicitly apply them: + +```bash +kubectl exec -i -n access-analyzer statefulset/keycloak -- bash < **Users** | -| Login fails with "invalid redirect URI" | Redirect URI not registered in the Azure App Registration or Enterprise Application | Add `https:///auth/realms/dspm/broker//endpoint` to the app registration | -| LDAP bind fails | Network policy blocking port 636 or 389, or incorrect service account credentials | Confirm firewall rules allow traffic from the cluster to the LDAP server; verify the service account DN and password | -| SAML signature validation fails | Wrong signing certificate used during configuration | Re-export the signing certificate from your IdP and reconfigure the connection | +This mapper is required. Access Analyzer matches pre-provisioned users to their IdP identity using the `email` claim on first sign-in. Without this mapper, authentication succeeds in Keycloak but the application cannot find the user. + +```bash +kubectl exec -n access-analyzer statefulset/keycloak -- \ + /opt/keycloak/bin/kcadm.sh create identity-provider/instances/entra-oidc/mappers -r dspm \ + -s name=email-mapper \ + -s identityProviderMapper=oidc-user-attribute-idp-mapper \ + -s identityProviderAlias=entra-oidc \ + -s 'config={"syncMode":"INHERIT","claim":"email","user.attribute":"email"}' +``` + +## Configure Entra ID (SAML) + +**Required values:** Tenant ID (no client ID or secret needed for SAML) + +**Step 1 — Create the SAML identity provider** + +```bash +kubectl exec -n access-analyzer statefulset/keycloak -- \ + /opt/keycloak/bin/kcadm.sh create identity-provider/instances -r dspm \ + -s alias=entra-saml \ + -s providerId=saml \ + -s enabled=true \ + -s trustEmail=true \ + -s 'firstBrokerLoginFlowAlias=first broker login' \ + -s 'config.singleSignOnServiceUrl=https://login.microsoftonline.com//saml2' \ + -s 'config.validateSignature=true' \ + -s 'config.wantAssertionsSigned=true' \ + -s 'config.nameIDPolicyFormat=urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress' +``` + +Replace `` with the customer's Azure AD tenant GUID. + +**Step 2 — Add the email mapper** + +Entra ID sends the email address as a URI-named SAML attribute. The mapper below maps that specific attribute to Keycloak's `email` field. The attribute URI is fixed for Entra ID and does not vary by customer. + +```bash +kubectl exec -n access-analyzer statefulset/keycloak -- \ + /opt/keycloak/bin/kcadm.sh create identity-provider/instances/entra-saml/mappers -r dspm \ + -s name=email-mapper \ + -s identityProviderMapper=saml-user-attribute-idp-mapper \ + -s identityProviderAlias=entra-saml \ + -s 'config={"syncMode":"INHERIT","attribute.name":"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress","user.attribute":"email"}' +``` + +## Configure Generic SAML + +**Required values:** SSO URL, Entity ID, signing certificate (PEM), email attribute name + +**Step 1 — Strip PEM headers from the signing certificate** + +Keycloak expects the certificate as bare base64 without `-----BEGIN CERTIFICATE-----` headers. Strip them before running the next step: + +```bash +SAML_SIGNING_CERT=$(cat .pem | grep -v '^-----' | tr -d '[:space:]') +``` + +**Step 2 — Create the SAML identity provider** + +```bash +kubectl exec -n access-analyzer statefulset/keycloak -- \ + /opt/keycloak/bin/kcadm.sh create identity-provider/instances -r dspm \ + -s alias=saml \ + -s providerId=saml \ + -s enabled=true \ + -s trustEmail=true \ + -s 'firstBrokerLoginFlowAlias=first broker login' \ + -s 'config.singleSignOnServiceUrl=' \ + -s 'config.entityId=' \ + -s "config.signingCertificate=$SAML_SIGNING_CERT" \ + -s 'config.validateSignature=true' \ + -s 'config.wantAssertionsSigned=true' +``` + +**Step 3 — Add the email mapper** + +Replace `` with the SAML attribute the customer's IdP uses to send the email address. Common values are `email`, `mail`, or a URI. Confirm with the customer's IdP administrator. + +```bash +kubectl exec -n access-analyzer statefulset/keycloak -- \ + /opt/keycloak/bin/kcadm.sh create identity-provider/instances/saml/mappers -r dspm \ + -s name=email-mapper \ + -s identityProviderMapper=saml-user-attribute-idp-mapper \ + -s identityProviderAlias=saml \ + -s 'config={"syncMode":"INHERIT","attribute.name":"","user.attribute":"email"}' +``` + +## Configure LDAP / Active Directory + +LDAP federation is architecturally different from OIDC and SAML. It creates a **User Federation component** rather than an identity provider instance. Users enter credentials directly on the Keycloak login page — no redirect occurs. + +**Required values:** LDAP server URL, service account DN, service account password, users base DN + +**Step 1 — Create the LDAP User Federation component** + +The command below targets Active Directory. For generic LDAP, replace `ad` with `other` and adjust the attribute values (`sAMAccountName` → `uid`, `cn` → `uid`, `objectGUID` → `entryUUID`, user object classes as appropriate). + +```bash +LDAP_ID=$(kubectl exec -i -n access-analyzer statefulset/keycloak -- bash <"]' \ + -s 'config.bindDn=[""]' \ + -s 'config.bindCredential=[""]' \ + -s 'config.usersDn=[""]' \ + -s 'config.usernameLDAPAttribute=["sAMAccountName"]' \ + -s 'config.rdnLDAPAttribute=["cn"]' \ + -s 'config.uuidLDAPAttribute=["objectGUID"]' \ + -s 'config.userObjectClasses=["person,organizationalPerson,user"]' \ + -s 'config.searchScope=["2"]' \ + -s 'config.importEnabled=["true"]' \ + -s 'config.syncRegistrations=["false"]' \ + -o --fields id | grep '"id"' | sed 's/.*"id"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/' +EOF +) +``` + +Pass the service account password via stdin heredoc to keep it out of audit logs. Note that LDAP federation values use JSON array syntax (`["value"]`) — this is a Keycloak API requirement for federation components. + +**Step 2 — Add the email attribute mapper** + +```bash +kubectl exec -n access-analyzer statefulset/keycloak -- \ + /opt/keycloak/bin/kcadm.sh create components -r dspm \ + -s name=email-mapper \ + -s providerType=org.keycloak.storage.ldap.mappers.LDAPStorageMapper \ + -s providerId=user-attribute-ldap-mapper \ + -s "parentId=$LDAP_ID" \ + -s '{"ldap.attribute":["mail"],"is.mandatory.in.ldap":["false"],"always.read.value.from.ldap":["false"],"read.only":["true"],"user.model.attribute":["email"]}' +``` + +Replace `mail` if the customer's directory uses a different attribute for email. Confirm with the customer's directory administrator. + +**Step 3 — Add the provider attribute mapper** + +This stamps all LDAP users with a `ldap_provider` attribute so Access Analyzer can identify them as LDAP-authenticated users: + +```bash +kubectl exec -n access-analyzer statefulset/keycloak -- \ + /opt/keycloak/bin/kcadm.sh create components -r dspm \ + -s name=ldap-provider-attribute \ + -s providerType=org.keycloak.storage.ldap.mappers.LDAPStorageMapper \ + -s providerId=hardcoded-attribute-mapper \ + -s "parentId=$LDAP_ID" \ + -s '{"attribute.value":["ldap"],"user.model.attribute":["ldap_provider"]}' +``` + +**Step 4 — Add the realm protocol mapper** + +This surfaces the `ldap_provider` attribute as the `identity_provider` claim in OIDC tokens. This mapper is created once at the realm level and applies to all LDAP federations: + +```bash +kubectl exec -n access-analyzer statefulset/keycloak -- \ + /opt/keycloak/bin/kcadm.sh create protocol-mappers/models -r dspm \ + --body '{ + "name": "ldap-identity-provider-claim", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "config": { + "user.attribute": "ldap_provider", + "claim.name": "identity_provider", + "jsonType.label": "String", + "id.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true" + } + }' +``` + +## Verify the configuration + +Run the verification script after configuring any IdP type. The script re-authenticates to the Keycloak Admin CLI and checks that all required components are present. + +**OIDC or SAML:** + +```bash +TYPE=oidc ALIAS=entra-oidc ./scripts/verify-idp-config.sh +TYPE=saml ALIAS=entra-saml ./scripts/verify-idp-config.sh +``` + +**LDAP (component check only):** + +```bash +TYPE=ldap ./scripts/verify-idp-config.sh +``` + +**LDAP (with connectivity test):** + +```bash +TYPE=ldap \ +LDAP_URL= \ +LDAP_BIND_DN= \ +LDAP_BIND_CREDENTIAL= \ +./scripts/verify-idp-config.sh +``` ## Next steps -After verifying the IdP connection: - -- [Identity Provider](../configurations/identity-provider.md) — pre-provision user accounts in Access Analyzer so users can sign in +After verifying the IdP connection, the application administrator must pre-provision user accounts in Access Analyzer before any users can sign in. See [Identity Provider](../configurations/identity-provider.md#pre-provision-user-accounts). From cd64af1d84215f8858fe2f9318cff1695fc4f880 Mon Sep 17 00:00:00 2001 From: Farrah Gamboa Date: Mon, 13 Apr 2026 13:49:53 -0400 Subject: [PATCH 26/62] =?UTF-8?q?Rebalance=20install/identity-provider.md?= =?UTF-8?q?=20=E2=80=94=20guided=20prose=20with=20commands?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds introductory context for each IdP section and explanatory sentences before each command so the article reads as a guided procedure rather than a script dump. Commands and technical accuracy are unchanged. Generated with AI Co-Authored-By: Claude Code --- .../2601/install/identity-provider.md | 44 +++++++++++-------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/docs/accessanalyzer/2601/install/identity-provider.md b/docs/accessanalyzer/2601/install/identity-provider.md index 3bd8169d41..8be736b8c0 100644 --- a/docs/accessanalyzer/2601/install/identity-provider.md +++ b/docs/accessanalyzer/2601/install/identity-provider.md @@ -10,7 +10,7 @@ sidebar_position: 50 This article is for the team performing the Access Analyzer deployment. It covers the cluster-level steps required to connect an identity provider to Keycloak. If you are an application administrator setting up user accounts after the IdP connection is in place, see [Identity Provider](../configurations/identity-provider.md). ::: -Access Analyzer uses Keycloak as its identity broker. Keycloak is deployed and configured automatically during installation. IdP connections are added after the cluster is running by running configuration scripts via `kubectl exec` into the Keycloak pod. +Access Analyzer uses Keycloak as its identity broker. Keycloak is deployed and configured automatically during installation. After the cluster is running, you connect your identity provider by running configuration scripts directly in the Keycloak pod using `kubectl exec`. Configuration scripts for each IdP type are included in the Access Analyzer distribution at `scripts/configure-.sh`. A verification script is available at `scripts/verify-idp-config.sh`. @@ -22,11 +22,11 @@ Confirm the following before running any configuration script: - You have `kubectl` access to the `access-analyzer` namespace - The required credentials have been collected from the customer's IdP or directory administrator (see [Identity Provider — Part 1](../configurations/identity-provider.md#part-1-configure-your-identity-provider)) - For LDAP: the Keycloak pod has network access to the LDAP server on port 636 (LDAPS) or 389 (LDAP) -- For private CA certificates: `customCaBundle` is set in the `infra` chart values and the cluster has been (re)deployed with it +- For private CA certificates: `customCaBundle` is set in the `infra` chart values and the cluster has been redeployed with it ## Authenticate to the Keycloak Admin CLI -Run this step before configuring any IdP type. It authenticates the Keycloak Admin CLI inside the pod using the bootstrap credentials injected at deploy time. +Run this step before configuring any IdP type. It authenticates the Keycloak Admin CLI inside the pod using the bootstrap credentials that were injected at deploy time. ```bash kubectl exec -n access-analyzer statefulset/keycloak -- bash -c ' @@ -38,15 +38,19 @@ kubectl exec -n access-analyzer statefulset/keycloak -- bash -c ' ``` :::note -The bootstrap admin credentials are read from environment variables already present in the pod. Do not pass them as command-line arguments — they would appear in Kubernetes audit logs. +The bootstrap admin credentials are read from environment variables already present in the pod. Don't pass them as command-line arguments — they would appear in Kubernetes audit logs. ::: ## Configure Entra ID (OIDC) -**Required values:** Tenant ID, Client ID, Client secret (from the Azure App Registration) +This creates an OIDC identity provider in the `dspm` realm that redirects users to Microsoft Entra ID for authentication. + +**Required values:** Tenant ID, Client ID, Client secret (from the customer's Azure App Registration) **Step 1 — Create the OIDC identity provider** +Creates the provider instance and points it at the tenant's OpenID Connect discovery endpoint. + ```bash kubectl exec -i -n access-analyzer statefulset/keycloak -- bash <`, ``, and `` with the values collected from the customer's Azure App Registration. Pass the client secret via stdin heredoc (as shown) to keep it out of Kubernetes audit logs. +Replace ``, ``, and `` with the values from the customer's Azure App Registration. The client secret is passed via stdin heredoc to keep it out of Kubernetes audit logs. **Step 2 — Refresh OIDC discovery endpoints** -Keycloak does not always populate the authorization, token, and JWKS URLs from the discovery endpoint at creation time. Run this step to explicitly apply them: +Keycloak doesn't always populate the authorization, token, and JWKS URLs from the discovery endpoint at creation time. This step fetches them explicitly and applies them to the provider. ```bash kubectl exec -i -n access-analyzer statefulset/keycloak -- bash <` with the customer's Azure AD tenant GUID. **Step 2 — Add the email mapper** -Entra ID sends the email address as a URI-named SAML attribute. The mapper below maps that specific attribute to Keycloak's `email` field. The attribute URI is fixed for Entra ID and does not vary by customer. +Entra ID sends the email address as a URI-named SAML attribute. This mapper translates it to Keycloak's `email` field. The attribute URI is fixed for Entra ID and doesn't vary by customer. ```bash kubectl exec -n access-analyzer statefulset/keycloak -- \ @@ -138,11 +144,13 @@ kubectl exec -n access-analyzer statefulset/keycloak -- \ ## Configure Generic SAML +This creates a SAML 2.0 identity provider for any SAML-compliant IdP (Okta, ADFS, and others). + **Required values:** SSO URL, Entity ID, signing certificate (PEM), email attribute name **Step 1 — Strip PEM headers from the signing certificate** -Keycloak expects the certificate as bare base64 without `-----BEGIN CERTIFICATE-----` headers. Strip them before running the next step: +Keycloak expects the certificate as bare base64 without `-----BEGIN CERTIFICATE-----` headers. Run this first to prepare the certificate value. ```bash SAML_SIGNING_CERT=$(cat .pem | grep -v '^-----' | tr -d '[:space:]') @@ -180,13 +188,13 @@ kubectl exec -n access-analyzer statefulset/keycloak -- \ ## Configure LDAP / Active Directory -LDAP federation is architecturally different from OIDC and SAML. It creates a **User Federation component** rather than an identity provider instance. Users enter credentials directly on the Keycloak login page — no redirect occurs. +LDAP federation works differently from OIDC and SAML. Instead of redirecting users to an external IdP, Keycloak connects directly to the customer's directory and users enter their credentials on the Access Analyzer login page. Configuring it creates a **User Federation component** rather than an identity provider instance, and requires three additional mappers beyond the basic connection. **Required values:** LDAP server URL, service account DN, service account password, users base DN **Step 1 — Create the LDAP User Federation component** -The command below targets Active Directory. For generic LDAP, replace `ad` with `other` and adjust the attribute values (`sAMAccountName` → `uid`, `cn` → `uid`, `objectGUID` → `entryUUID`, user object classes as appropriate). +This connects Keycloak to the customer's LDAP or Active Directory. The command below targets Active Directory. For generic LDAP, replace `ad` with `other` and adjust attribute names (`sAMAccountName` → `uid`, `cn` → `uid`, `objectGUID` → `entryUUID`, user object classes as appropriate). ```bash LDAP_ID=$(kubectl exec -i -n access-analyzer statefulset/keycloak -- bash < Date: Mon, 13 Apr 2026 15:03:33 -0400 Subject: [PATCH 27/62] AA26: Add per-version KB source routing and v2601 KB placeholder - products.js: add kbSource field to ProductVersion typedef and set kbSource: 'docs/kb/accessanalyzer-2601' on the v2601 version entry - copy-kb-to-versions.mjs: resolve KB source per-version using optional kbSource override with fallback to product-level default; move source existence check inside the version loop; add versionSources validation - docs/kb/accessanalyzer-2601: new KB source directory for v2601 with landing page (index.md), Knowledge Base category config (_category_.json), and KB article template/style guide (kb-article-template.md) v12.0 and v11.6 continue using docs/kb/accessanalyzer/ unchanged. --- docs/kb/accessanalyzer-2601/_category_.json | 10 + docs/kb/accessanalyzer-2601/index.md | 18 ++ .../kb-article-template.md | 185 ++++++++++++++++++ kb_allowlist.json | 67 ------- scripts/copy-kb-to-versions.mjs | 40 +++- src/config/products.js | 2 + 6 files changed, 246 insertions(+), 76 deletions(-) create mode 100644 docs/kb/accessanalyzer-2601/_category_.json create mode 100644 docs/kb/accessanalyzer-2601/index.md create mode 100644 docs/kb/accessanalyzer-2601/kb-article-template.md diff --git a/docs/kb/accessanalyzer-2601/_category_.json b/docs/kb/accessanalyzer-2601/_category_.json new file mode 100644 index 0000000000..7ad393fb13 --- /dev/null +++ b/docs/kb/accessanalyzer-2601/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Knowledge Base", + "position": 999, + "collapsed": true, + "collapsible": true, + "link": { + "type": "doc", + "id": "index" + } +} diff --git a/docs/kb/accessanalyzer-2601/index.md b/docs/kb/accessanalyzer-2601/index.md new file mode 100644 index 0000000000..0574c80c1d --- /dev/null +++ b/docs/kb/accessanalyzer-2601/index.md @@ -0,0 +1,18 @@ +--- +title: "Access Analyzer Knowledge Base" +description: "Access Analyzer v2601 knowledge base articles and troubleshooting guides" +slug: accessanalyzer-2601 +--- + +# Access Analyzer Knowledge Base + +Welcome to the Access Analyzer knowledge base. Browse troubleshooting guides, configuration instructions, and best practices for Access Analyzer v2601. + +Use the search function above to find specific articles or browse through all Access Analyzer KB articles in this section. + +## Need Help? + +If you cannot find what you are looking for: +1. Use the search function above +2. Check the main Access Analyzer documentation +3. Contact [Netwrix support](https://www.netwrix.com/support.html) diff --git a/docs/kb/accessanalyzer-2601/kb-article-template.md b/docs/kb/accessanalyzer-2601/kb-article-template.md new file mode 100644 index 0000000000..46b8f45af8 --- /dev/null +++ b/docs/kb/accessanalyzer-2601/kb-article-template.md @@ -0,0 +1,185 @@ +--- +description: >- + [One sentence. Keyword-rich, SEO-friendly summary of what problem this + article solves or what task it covers. Example: "When the Access Analyzer + scan job fails with error X, the host is unreachable. This article describes + the cause and provides steps to resolve the connectivity issue."] +keywords: + - access analyzer + - "[keyword 2 — use exact phrasing a customer would search for]" + - "[keyword 3 — include error codes or unique identifiers when relevant]" + - "[keyword 4]" + - "[keyword 5]" + - "[keyword 6]" + - "[keyword 7]" + - "[keyword 8 — aim for 8–12 total keywords]" +products: + - access-analyzer +sidebar_label: "KB Article Template" +tags: [] +title: "KB Article Template and Style Guide" +knowledge_article_id: kA0Qk000000XXXXKAA +--- + +# KB Article Template and Style Guide + +This file is a placeholder and authoring guide for Access Analyzer v2601 knowledge base articles. Copy this file, rename it, and replace the placeholder content with the actual article. Remove this introduction paragraph before publishing. + +--- + + + + + + + +## Symptom + + + +When running [specific job or action] in Netwrix Access Analyzer, the following error appears: + +```text +[Paste the exact error message here, as it appears in the UI or log.] +``` + +[Optional: one additional sentence describing secondary symptoms, e.g., "The job fails immediately and no scan results are produced."] + +## Cause + + + +This error occurs when [plain-language explanation of the root cause]. + +## Resolution + + + +1. Navigate to **[Menu] > [Submenu]** in the Netwrix Access Analyzer console. +2. Select **[Option]** and click **[Button]**. +3. In the **[Field Name]** field, enter [description of required value]. +4. Click **Save** to apply the changes. +5. Re-run the [job or scan] to confirm the issue is resolved. + +> **NOTE:** [Use for important context that does not fit inline. Use **IMPORTANT:** instead for warnings about irreversible actions or data loss.] + +## Related Links + +- [Netwrix Access Analyzer Documentation — System Requirements](URL) +- [Link text describing destination — add a line for each relevant resource](URL) + +--- + + + + + +--- + +## Style Quick Reference + +Remove this section before publishing. + +| Element | Format | Example | +|---|---|---| +| UI button / menu / tab / field | **Bold** | Click **Save** | +| Command-line input | `` `backtick` `` | Run `npm start` | +| Error message (full block) | ` ```text ``` ` fenced block | See Symptom section above | +| File path (inline) | `` `backtick` `` | Open `` `C:\Program Files\Netwrix` `` | +| Important callout | `> **IMPORTANT:** ...` | Warns of irreversible actions | +| Note callout | `> **NOTE:** ...` | Non-critical supplemental info | +| External link | `[Name ⸱ Company 🡥](URL)` | [SMB Security ⸱ Microsoft 🡥](URL) | +| Image alt text | [Action shown] + [key UI elements] | "Dialog box for scan settings with Schedule tab active" | +| Product — first mention | Full name | Netwrix Access Analyzer | +| Product — subsequent mentions | Short name | Access Analyzer | + +### Title Rules by Article Type + +| Type | Format | Good Example | Bad Example | +|---|---|---|---| +| How-To | [Action Gerund] [Specific Task] | Configuring LDAP Authentication | How to Configure LDAP? | +| Error Resolution | Error: [Unique Code or Message] | Error: Host Unreachable 0x80070005 | Error: Something Went Wrong | +| Symptom Resolution | [Component] [Symptom] [Context] | Scan Jobs Failing After Upgrade | Scans Not Working | + +### Voice and Tone + +- Use "you" (second person) when addressing the reader. +- Write in active voice: "Click **Save**" not "**Save** should be clicked." +- Avoid: "simply," "just," "easy," "obviously," "leverage," "utilize." +- Write out contractions: "do not" not "don't," "cannot" not "can't." +- No exclamation marks, including in callouts. +- One idea per paragraph; paragraphs to 3–4 sentences maximum. diff --git a/kb_allowlist.json b/kb_allowlist.json index 1e5475e5a7..29743496ba 100644 --- a/kb_allowlist.json +++ b/kb_allowlist.json @@ -1,72 +1,5 @@ { - "1secure": [ - "current" - ], "accessanalyzer": [ - "11.6", - "12.0", "2601" - ], - "accessinformationcenter": [ - "11.6", - "12.0" - ], - "activitymonitor": [ - "7.1", - "8.0", - "9.0" - ], - "auditor": [ - "10.6", - "10.7", - "10.8" - ], - "changetracker": [ - "8.0", - "8.1" - ], - "dataclassification": [ - "5.6.2", - "5.7" - ], - "directorymanager": [ - "11.0", - "11.1" - ], - "endpointprotector": [ - "current" - ], - "identityrecovery": [ - "2.6", - "3.1" - ], - "passwordpolicyenforcer": [ - "10.2", - "11.0", - "11.1" - ], - "passwordreset": [ - "3.23", - "3.3" - ], - "privilegesecure": [ - "25.12", - "4.1", - "4.2" - ], - "privilegesecurediscovery": [ - "current" - ], - "recoveryforactivedirectory": [ - "2.6", - "3.1" - ], - "threatmanager": [ - "3.0", - "3.1" - ], - "threatprevention": [ - "7.5", - "8.0" ] } diff --git a/scripts/copy-kb-to-versions.mjs b/scripts/copy-kb-to-versions.mjs index b761e1bd8a..1eb8a2d4cf 100644 --- a/scripts/copy-kb-to-versions.mjs +++ b/scripts/copy-kb-to-versions.mjs @@ -60,6 +60,14 @@ function buildConfig() { return v.version; }); + // Build per-version KB source overrides (from optional kbSource field on each version entry) + const versionSources = {}; + product.versions.forEach(v => { + if (v.kbSource) { + versionSources[v.version] = v.kbSource; + } + }); + // Special handling: KB folder name mapping (for legacy naming) const kbFolderName = productId === 'recoveryforactivedirectory' ? 'recoveryad' : @@ -75,6 +83,7 @@ function buildConfig() { config[productId] = { versions: versions, + versionSources: versionSources, source: `docs/kb/${kbFolderName}`, destinationPattern: destinationPattern }; @@ -253,6 +262,16 @@ function validateConfig(CONFIG) { // Validate source path stays under repo root validateDestinationPath(productConfig.source); + // Validate per-version source overrides + if (productConfig.versionSources) { + for (const [ver, src] of Object.entries(productConfig.versionSources)) { + if (typeof src !== 'string') { + throw new Error(`Invalid versionSources[${ver}] for product ${product}: expected string`); + } + validateDestinationPath(src); + } + } + // Validate destination pattern stays under repo root (sample substitution) const testDest = productConfig.destinationPattern.replace('{version}', '1.0'); validateDestinationPath(testDest); @@ -600,13 +619,6 @@ function main() { console.log(`\n📚 Product: ${product}`); console.log('-'.repeat(60)); - // Check if source exists - if (!fs.existsSync(config.source)) { - console.log(`⚠️ Source not found: ${config.source}`); - totalVersionErrors++; - continue; - } - // Process each version (isolated) for (const version of config.versions) { // Skip if filtered out @@ -618,15 +630,25 @@ function main() { // Validate version format validateVersionFormat(version); + // Resolve KB source: use per-version override if defined, otherwise fall back to product default + const versionSource = config.versionSources?.[version] ?? config.source; + const destination = config.destinationPattern.replace('{version}', version); // Validate destination path validateDestinationPath(destination); console.log(`\n 📖 Version: ${version}`); - console.log(` Source: ${config.source}`); + console.log(` Source: ${versionSource}`); console.log(` Dest: ${destination}`); + // Check if source exists (per-version, since sources may differ) + if (!fs.existsSync(versionSource)) { + console.log(` ⚠️ Source not found: ${versionSource}`); + totalVersionErrors++; + continue; + } + // If --clean is set, remove destination first if (isClean && fs.existsSync(destination)) { if (!isDryRun) { @@ -644,7 +666,7 @@ function main() { // Copy KB content (always happens, regardless of --clean) if (!isDryRun) { const errorCount = { count: 0 }; - const result = copyDirectorySync(config.source, destination, config.source, product, errorCount); + const result = copyDirectorySync(versionSource, destination, versionSource, product, errorCount); if (errorCount.count > 0) { console.log(` ⚠️ Copied with ${errorCount.count} file errors`); diff --git a/src/config/products.js b/src/config/products.js index 2534178506..e9a5d5c2b3 100644 --- a/src/config/products.js +++ b/src/config/products.js @@ -17,6 +17,7 @@ * @property {string} label - Display label for the version * @property {boolean} isLatest - Whether this is the latest version * @property {string} [sidebarFile] - Custom sidebar file path (defaults to generated path) + * @property {string} [kbSource] - Optional override for the KB source directory for this version (relative to repo root). When set, this version pulls KB articles from this directory instead of the product-level default (docs/kb//). */ /** @@ -65,6 +66,7 @@ export const PRODUCTS = [ label: '2601', isLatest: false, sidebarFile: './sidebars/accessanalyzer/2601.js', + kbSource: 'docs/kb/accessanalyzer-2601', }, { version: '12.0', From 7d957fcfdbf0e09ed0e415f1f8edcbe5fde7f2b3 Mon Sep 17 00:00:00 2001 From: carlos-mejia_nwx Date: Mon, 13 Apr 2026 15:54:09 -0400 Subject: [PATCH 28/62] AA26: Add placeholder connector requirement pages for NAS file servers Adds stub pages (content coming soon) for: - NetApp ONTAP - Dell Isilon / PowerScale - Dell Unity - Dell EMC Celerra - Dell EMC VNX --- .../2601/connectors/file-servers/celerra.md | 9 +++++++++ .../2601/connectors/file-servers/dell-unity.md | 9 +++++++++ .../2601/connectors/file-servers/isilon-powerscale.md | 9 +++++++++ .../2601/connectors/file-servers/netapp.md | 8 ++++---- docs/accessanalyzer/2601/connectors/file-servers/vnx.md | 9 +++++++++ 5 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 docs/accessanalyzer/2601/connectors/file-servers/celerra.md create mode 100644 docs/accessanalyzer/2601/connectors/file-servers/dell-unity.md create mode 100644 docs/accessanalyzer/2601/connectors/file-servers/isilon-powerscale.md create mode 100644 docs/accessanalyzer/2601/connectors/file-servers/vnx.md diff --git a/docs/accessanalyzer/2601/connectors/file-servers/celerra.md b/docs/accessanalyzer/2601/connectors/file-servers/celerra.md new file mode 100644 index 0000000000..2dd3e5a95f --- /dev/null +++ b/docs/accessanalyzer/2601/connectors/file-servers/celerra.md @@ -0,0 +1,9 @@ +--- +title: "Dell EMC Celerra" +description: "Supported platforms, permissions, and network ports for Dell EMC Celerra CIFS/SMB scanning" +sidebar_position: 50 +--- + +# Dell EMC Celerra + +*Content coming soon.* diff --git a/docs/accessanalyzer/2601/connectors/file-servers/dell-unity.md b/docs/accessanalyzer/2601/connectors/file-servers/dell-unity.md new file mode 100644 index 0000000000..98af08325c --- /dev/null +++ b/docs/accessanalyzer/2601/connectors/file-servers/dell-unity.md @@ -0,0 +1,9 @@ +--- +title: "Dell Unity" +description: "Supported platforms, permissions, and network ports for Dell Unity CIFS/SMB scanning" +sidebar_position: 40 +--- + +# Dell Unity + +*Content coming soon.* diff --git a/docs/accessanalyzer/2601/connectors/file-servers/isilon-powerscale.md b/docs/accessanalyzer/2601/connectors/file-servers/isilon-powerscale.md new file mode 100644 index 0000000000..9a7dc21998 --- /dev/null +++ b/docs/accessanalyzer/2601/connectors/file-servers/isilon-powerscale.md @@ -0,0 +1,9 @@ +--- +title: "Dell Isilon / PowerScale" +description: "Supported platforms, permissions, and network ports for Dell Isilon and PowerScale CIFS/SMB scanning" +sidebar_position: 30 +--- + +# Dell Isilon / PowerScale + +*Content coming soon.* diff --git a/docs/accessanalyzer/2601/connectors/file-servers/netapp.md b/docs/accessanalyzer/2601/connectors/file-servers/netapp.md index 17eab35605..599ec71fcc 100644 --- a/docs/accessanalyzer/2601/connectors/file-servers/netapp.md +++ b/docs/accessanalyzer/2601/connectors/file-servers/netapp.md @@ -1,9 +1,9 @@ --- -title: "NetApp" -description: "Connector requirements for NetApp file servers" -sidebar_position: 50 +title: "NetApp ONTAP" +description: "Supported platforms, permissions, and network ports for NetApp ONTAP CIFS/SMB scanning" +sidebar_position: 20 --- -# NetApp +# NetApp ONTAP *Content coming soon.* diff --git a/docs/accessanalyzer/2601/connectors/file-servers/vnx.md b/docs/accessanalyzer/2601/connectors/file-servers/vnx.md new file mode 100644 index 0000000000..f8c38b1ab2 --- /dev/null +++ b/docs/accessanalyzer/2601/connectors/file-servers/vnx.md @@ -0,0 +1,9 @@ +--- +title: "Dell EMC VNX" +description: "Supported platforms, permissions, and network ports for Dell EMC VNX file server CIFS/SMB scanning" +sidebar_position: 60 +--- + +# Dell EMC VNX + +*Content coming soon.* From 9a95eee2b2c29100299ec35b46bc0793128b06fd Mon Sep 17 00:00:00 2001 From: Farrah Gamboa Date: Mon, 13 Apr 2026 22:55:57 -0400 Subject: [PATCH 29/62] AA26: Add installer command reference page under Installation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds docs/accessanalyzer/2601/install/install-commands.md — a practical guide covering the curl-based install command, version pinning via DSPM_TARGET_REVISION, common options (dry-run, storage dirs, size, log-level), warning guidance with per-type decision table, preflight requirements, and exit code triage. Support-only flags (--skip-preflight, --k3s-version, --argocd-version, --argocd-namespace, --use-mirrored-images, --kubeconfig) are excluded from this page; a companion KB article will follow once the accessanalyzer-2601 KB directory is established. Generated with AI Co-Authored-By: Claude Code --- .../2601/install/install-commands.md | 223 ++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 docs/accessanalyzer/2601/install/install-commands.md diff --git a/docs/accessanalyzer/2601/install/install-commands.md b/docs/accessanalyzer/2601/install/install-commands.md new file mode 100644 index 0000000000..a267747f8e --- /dev/null +++ b/docs/accessanalyzer/2601/install/install-commands.md @@ -0,0 +1,223 @@ +--- +title: "Installer Command Reference" +description: "Options you can pass to the Access Analyzer installer to customize your deployment" +sidebar_position: 20 +--- + +# Installer Command Reference + +Access Analyzer is installed using a single curl command that downloads and runs the installer. You can pass options to this command to customize how the product is deployed on your server. Most installations need only a license key and accept all defaults. + +## Before You Run the Installer + +### Set your license key + +Export your license key as an environment variable before running any installer command. This keeps the key out of your shell history and makes it available to the installer automatically. + +```bash +export LICENSE_KEY='[YOUR_LICENSE_KEY]' +``` + +Replace `[YOUR_LICENSE_KEY]` with the license key provided by Netwrix. All examples on this page assume you have exported this variable. + +:::warning +Your license key authenticates access to the Netwrix package registry. Don't share it, commit it to version control, or leave it visible in script files. +::: + +### Choose an installer version + +**Without specifying a version**, the installer downloads the latest stable release automatically. This is appropriate for initial deployments and when you're ready to take the latest release: + +```bash +# Set the Keygen license key variable +export LICENSE_KEY='[YOUR_LICENSE_KEY]' + +# Run installation +curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash - +``` + +**To pin to a specific release** — recommended when you want to control when upgrades happen during your organization's patching cycle — export the version before running the same curl command: + +```bash +# Set the Keygen license key variable +export LICENSE_KEY='[YOUR_LICENSE_KEY]' + +# Pin to a specific release version +export DSPM_TARGET_REVISION='[VERSION]' + +# Run installation +curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash - +``` + +:::note +The version number for each Access Analyzer release will be published here before general availability. Replace `[VERSION]` with the version string provided in the release notes. +::: + +## Running the Installer + +When you run the curl command above, the installer automatically: + +1. Runs preflight checks to verify your system meets requirements +2. Installs Kubernetes (k3s v1.33.4, the version validated by Netwrix for this release) +3. Deploys ArgoCD as the GitOps controller +4. Pulls and deploys the Access Analyzer application stack from the Netwrix registry +5. Waits for all components to become healthy + +Installation typically takes 15–30 minutes depending on network speed and hardware. + +### Passing additional options + +To customize the installation, add options after `bash -s --`. Everything after `--` is forwarded to the installer: + +```bash +curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- --dry-run +``` + +For options that take a value, such as custom storage paths: + +```bash +curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- \ + --postgres-data-dir /mnt/ssd/postgres \ + --clickhouse-data-dir /mnt/nvme/clickhouse +``` + +The available options are described in the sections below. + +### Validate before installing (dry run) + +To check system readiness without making any changes, add `--dry-run`: + +```bash +curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- --dry-run +``` + +Dry run performs all preflight checks and shows what the installer would do, without modifying the system. Use this before deploying to production to confirm your server meets requirements. + +## Customizing the Installation + +### Directing database storage to a dedicated volume + +By default, the PostgreSQL and ClickHouse databases store data on the root filesystem. For production deployments, direct each database to a dedicated volume to keep database growth from filling your root disk: + +```bash +curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- \ + --postgres-data-dir /mnt/ssd/postgres \ + --clickhouse-data-dir /mnt/nvme/clickhouse +``` + +Each directory must already exist and be writable before the installer runs. The path must: + +- Start with `/` (absolute path) +- Not be a system directory (`/bin`, `/etc`, `/usr`, `/var/log`, and others) +- Not contain special characters: `"`, `'`, `\`, `` ` ``, or `$` + +### Scaling resources for larger servers + +The `--size` option scales CPU and memory allocations for all Access Analyzer workloads. The default value of `1` suits the minimum recommended hardware (16 GB RAM, 4 vCPUs). Increase this on servers with more resources: + +```bash +curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- --size 2 +``` + +The valid range is `1` through `10`. Contact Netwrix Support for guidance on which value is appropriate for your server. + +### Increasing log verbosity + +If an installation fails and you need more detail to diagnose the problem, run with debug logging: + +```bash +curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- --log-level debug +``` + +The log is written to `/var/log/dspm-installer.log`. Accepted values are `debug`, `info`, `warn`, and `error`. The default is `info`. Terminal progress output is not affected — only the log file verbosity changes. + +## If the Installer Stops with Warnings + +By default, the installer stops when a preflight warning is detected. In some cases you may know the warning is acceptable for your environment. Use `--accept-warnings` to allow installation to continue: + +```bash +curl -sLfo - "https://raw.pkg.keygen.sh/v1/accounts/netwrix/artifacts/dspm-install.sh?auth=license:$LICENSE_KEY" | bash -s -- --accept-warnings +``` + +Before using this option, identify which warning is being reported and review the guidance below: + +| Warning | What it means | Recommended action | +|---|---|---| +| Overlay kernel module not loaded | The `overlay` module isn't active. k3s may load it automatically during installation. | Generally safe to accept. Monitor the installation for container errors. | +| Unrecognized Linux distribution | The installer didn't recognize your OS as a supported RHEL or Debian variant. | Verify your OS is a supported version before accepting. Contact Netwrix Support if unsure. | +| SELinux in enforcing mode | SELinux may block k3s container operations. | Accept only if you have confirmed your SELinux policy permits k3s. If unsure, set SELinux to permissive mode first. | +| Antivirus software detected | An antivirus agent is running and may interfere with container storage paths. | Configure exclusions for the k3s paths listed in the warning output before accepting. | + +If you're unsure whether a warning is safe to accept, contact Netwrix Support before proceeding. + +## Preflight Check Requirements + +The installer checks the following before installation begins. Results are written to `/var/log/dspm-preflight.json`. + +| Check | Fail | Warn | +|---|---|---| +| **RAM** | Less than 8 GB total | Less than 16 GB total | +| **CPU** | Fewer than 2 cores | — | +| **Disk** | Less than 20 GB free on `/var` | — | +| **Cgroups** | Not available at `/sys/fs/cgroup` | — | +| **Overlay kernel module** | — | Not loaded | +| **OS family** | — | Unrecognized Linux distribution | +| **SELinux** | — | SELinux in enforcing mode | +| **Antivirus** | — | Known antivirus software detected | +| **Network** | DNS resolution fails for a required domain | TCP connection timeout to a required domain | + +A **FAIL** result stops the installer and must be resolved. A **WARN** result also stops the installer by default — see [If the Installer Stops with Warnings](#if-the-installer-stops-with-warnings) above. + +For the full list of required network domains, see [Network and Port Requirements](/docs/accessanalyzer/2601/install/system/network). + +## If the Installer Fails + +When the installer exits with an error, check the log: + +```bash +cat /var/log/dspm-installer.log +``` + +The exit code indicates which phase failed: + +| Code | Phase | What to do | +|---|---|---| +| `0` | — | Installation completed successfully | +| `1` | General | Review the log for the specific error message | +| `10` | License | Verify your license key is correct and hasn't expired | +| `50` | k3s | Review the log and contact Netwrix Support | +| `60` | ArgoCD | Review the log and contact Netwrix Support | +| `70` | App startup | Applications didn't become healthy within 30 minutes. Run `kubectl get pods -n access-analyzer` to check pod status, then contact Netwrix Support | +| `71` | App startup | A pod entered a permanent failure state. Run `kubectl get pods -A` to identify it, then contact Netwrix Support | +| `80` | Preflight | Resolve the reported system requirement and retry | + +## Environment Variables + +If you prefer not to pass options on the command line — for example, in an automated deployment script — several options can be set as environment variables. These are picked up automatically if they are exported before the install command runs. + +| Environment variable | Equivalent option | +|---|---| +| `LICENSE_KEY` | `--license-key` | +| `DRY_RUN` | `--dry-run` | +| `ACCEPT_WARNINGS` | `--accept-warnings` | +| `LOG_LEVEL` | `--log-level` | +| `POSTGRES_DATA_DIR` | `--postgres-data-dir` | +| `CLICKHOUSE_DATA_DIR` | `--clickhouse-data-dir` | + +When the same option is set as both an environment variable and a command-line flag, the flag takes precedence. + +## Configuration File + +If you run the installer on multiple servers with the same options, you can store common settings in `~/.dspm/installer.yaml` to avoid repeating them every time: + +```yaml +# ~/.dspm/installer.yaml +log-level: info +postgres-data-dir: /mnt/ssd/postgres +clickhouse-data-dir: /mnt/nvme/clickhouse +size: 2 +``` + +Don't store your license key in this file. Use the `LICENSE_KEY` environment variable instead. + +**Precedence order** (highest to lowest): command-line flags > environment variables > configuration file > defaults. From 837d49836d39df5f0f8265b66724b916c9eb391e Mon Sep 17 00:00:00 2001 From: Farrah Gamboa Date: Tue, 14 Apr 2026 12:40:44 -0400 Subject: [PATCH 30/62] Add migration KB articles and adoption framing for AA26 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a complete migration knowledge base for customers deploying AA26 alongside Netwrix Access Analyzer (formerly StealthAUDIT). Covers credentials, target servers/host lists, job schedules, historical audit data strategy, and a planning checklist. Framing throughout emphasizes incremental adoption — customers can deploy AA26 one connector type, site, or business unit at a time with no requirement to decommission the legacy product. Generated with AI Co-Authored-By: Claude Code --- .../migration/_category_.json | 10 + .../migration/audit-data-strategy.md | 126 ++++++ .../kb/accessanalyzer-2601/migration/index.md | 107 +++++ .../migration/migrate-credentials.md | 237 ++++++++++ .../migration/migrate-schedules.md | 345 +++++++++++++++ .../migration/migrate-target-servers.md | 417 ++++++++++++++++++ .../migration/migration-checklist.md | 170 +++++++ .../2601/migration/_after-login.png | Bin 0 -> 72560 bytes .../accessanalyzer/2601/migration/_login.png | Bin 0 -> 15603 bytes .../add-service-account-certificate.png | Bin 0 -> 126602 bytes .../add-service-account-client-secret.png | Bin 0 -> 128026 bytes .../migration/add-service-account-form.png | Bin 0 -> 129106 bytes .../migration/add-service-account-initial.png | Bin 0 -> 129069 bytes ...add-service-account-type-dropdown-open.png | Bin 0 -> 129069 bytes .../add-service-account-username-password.png | Bin 0 -> 129106 bytes .../create-source-group-configure.png | Bin 0 -> 108906 bytes .../create-source-group-file-server-setup.png | Bin 0 -> 113863 bytes .../create-source-group-file-server.png | Bin 0 -> 113719 bytes .../migration/create-source-group-filled.png | Bin 0 -> 110181 bytes .../create-source-group-scan-config.png | Bin 0 -> 113719 bytes .../migration/create-source-group-step1.png | Bin 0 -> 110087 bytes .../create-source-group-type-select.png | Bin 0 -> 110087 bytes .../2601/migration/scans-list.png | Bin 0 -> 158840 bytes .../2601/migration/service-accounts-list.png | Bin 0 -> 134923 bytes .../2601/migration/source-groups-list.png | Bin 0 -> 95691 bytes .../2601/migration/type-dropdown-open.png | Bin 0 -> 132149 bytes 26 files changed, 1412 insertions(+) create mode 100644 docs/kb/accessanalyzer-2601/migration/_category_.json create mode 100644 docs/kb/accessanalyzer-2601/migration/audit-data-strategy.md create mode 100644 docs/kb/accessanalyzer-2601/migration/index.md create mode 100644 docs/kb/accessanalyzer-2601/migration/migrate-credentials.md create mode 100644 docs/kb/accessanalyzer-2601/migration/migrate-schedules.md create mode 100644 docs/kb/accessanalyzer-2601/migration/migrate-target-servers.md create mode 100644 docs/kb/accessanalyzer-2601/migration/migration-checklist.md create mode 100644 static/images/accessanalyzer/2601/migration/_after-login.png create mode 100644 static/images/accessanalyzer/2601/migration/_login.png create mode 100644 static/images/accessanalyzer/2601/migration/add-service-account-certificate.png create mode 100644 static/images/accessanalyzer/2601/migration/add-service-account-client-secret.png create mode 100644 static/images/accessanalyzer/2601/migration/add-service-account-form.png create mode 100644 static/images/accessanalyzer/2601/migration/add-service-account-initial.png create mode 100644 static/images/accessanalyzer/2601/migration/add-service-account-type-dropdown-open.png create mode 100644 static/images/accessanalyzer/2601/migration/add-service-account-username-password.png create mode 100644 static/images/accessanalyzer/2601/migration/create-source-group-configure.png create mode 100644 static/images/accessanalyzer/2601/migration/create-source-group-file-server-setup.png create mode 100644 static/images/accessanalyzer/2601/migration/create-source-group-file-server.png create mode 100644 static/images/accessanalyzer/2601/migration/create-source-group-filled.png create mode 100644 static/images/accessanalyzer/2601/migration/create-source-group-scan-config.png create mode 100644 static/images/accessanalyzer/2601/migration/create-source-group-step1.png create mode 100644 static/images/accessanalyzer/2601/migration/create-source-group-type-select.png create mode 100644 static/images/accessanalyzer/2601/migration/scans-list.png create mode 100644 static/images/accessanalyzer/2601/migration/service-accounts-list.png create mode 100644 static/images/accessanalyzer/2601/migration/source-groups-list.png create mode 100644 static/images/accessanalyzer/2601/migration/type-dropdown-open.png diff --git a/docs/kb/accessanalyzer-2601/migration/_category_.json b/docs/kb/accessanalyzer-2601/migration/_category_.json new file mode 100644 index 0000000000..5e5042c29e --- /dev/null +++ b/docs/kb/accessanalyzer-2601/migration/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Migration from StealthAUDIT / Access Analyzer", + "position": 10, + "collapsed": false, + "collapsible": true, + "link": { + "type": "doc", + "id": "index" + } +} diff --git a/docs/kb/accessanalyzer-2601/migration/audit-data-strategy.md b/docs/kb/accessanalyzer-2601/migration/audit-data-strategy.md new file mode 100644 index 0000000000..2026c4674f --- /dev/null +++ b/docs/kb/accessanalyzer-2601/migration/audit-data-strategy.md @@ -0,0 +1,126 @@ +--- +title: "Historical Audit Data and Parallel Operation" +description: "How to maintain access to historical audit records in the legacy SQL Server database while running Access Analyzer 26 alongside your existing environment" +keywords: + - audit data migration + - sql server audit records + - historical data + - fsactivity migration + - adactivity migration + - compliance continuity + - stealthaudit database + - parallel operation +products: + - access-analyzer +sidebar_label: "Historical Audit Data Strategy" +tags: + - migration + - audit-data +--- + +# Historical Audit Data and Parallel Operation + +## Overview + +Access Analyzer 26 uses a separate database stack (ClickHouse and PostgreSQL) and does not connect to or read from the legacy SQL Server database. Historical audit records collected by the legacy system remain where they are — in the original SQL Server database — and are not affected by deploying AA26. + +This means the two products operate independently. The legacy system continues collecting data for any sources still under its management. AA26 collects data for the sources you have added to it. Neither system interferes with the other. + +This article explains what data lives in the legacy database, how to keep it accessible, and what AA26 collects for sources under its management. + +--- + +## What remains in the SQL Server database + +The following categories of collected data live in the legacy NAA SQL Server database and are not transferred to AA26: + +| Data Category | Description | Example Tables | +| --- | --- | --- | +| **File system activity** | User access events on file shares and NAS devices | `SA_*_FSActivity` | +| **Active Directory changes** | Object creation, deletion, and modification events | `SA_*_ADActivity` | +| **Exchange mailbox activity** | Email access, send, and receive events | `SA_*_MailboxActivity` | +| **Sensitive data findings** | Files containing detected sensitive content | `SA_*_SensitiveData` | +| **Permissions snapshots** | Point-in-time access rights inventories | `SA_*_Permissions` | +| **Group membership history** | Historical group membership records | `SA_*_GroupMembership` | + +Table names in the legacy database use the format `SA_[JobName]_[TableName]`. The exact names vary by your configuration and which jobs were running. + +--- + +## Maintaining access to historical records + +The legacy SQL Server database and the NAA application continue to operate normally after you deploy AA26. No data is deleted or modified by AA26's deployment. + +### Recommended access approach + +1. **Retain the NAA SQL Server instance** and its database. Do not decommission or drop the database while any historical records it contains might be needed for audit or compliance purposes. + +2. **Avoid duplicate collection for shared sources.** If a source is added to AA26, the legacy job targeting the same host can be stopped to avoid collecting the same data twice. Sources and jobs that have not yet moved to AA26 continue running without interruption. + +3. **Grant read-only access to authorized users** — security analysts, compliance officers, and legal teams — who might need to query historical records for audit or investigation purposes. + +4. **Document the coverage boundary per source.** For any source that moves to AA26, note the date AA26 began collecting data for it. This lets you query the correct system when responding to audit requests that span the transition. + +### Querying historical data + +Use SQL Server Management Studio (SSMS), a reporting tool, or the legacy NAA Web Console to query historical records. The legacy REST API also supports read-only access to job output tables. + +Example: retrieve all file access events for a specific user in a specific date range: + +```sql +SELECT + EventTime, + UserName, + HostName, + SharePath, + ObjectPath, + AccessType, + AccessMask +FROM + SA_FileSystem_FSActivity -- Adjust table name to match your job name +WHERE + UserName = 'DOMAIN\jsmith' + AND EventTime BETWEEN '2024-01-01' AND '2024-12-31' +ORDER BY + EventTime DESC; +``` + +The exact table and column names depend on your NAA job configuration. Use `SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE '%Activity%'` to enumerate activity tables in your database. + +--- + +## What Access Analyzer 26 collects + +For sources added to AA26, the product collects the following data through its configured scans: + +| Scan Type | Data Collected | Stored In | +| --- | --- | --- | +| **Access Scan** | Permissions, group memberships, and access rights | ClickHouse (intelligence tables) | +| **Sensitive Data Scan** | Files and objects containing sensitive content | ClickHouse (intelligence tables) | +| **IAM Sync** | Active Directory and Entra ID users, groups, and memberships | ClickHouse (intelligence tables) | + +AA26 does not collect real-time file system activity events (file open, read, write, delete) in this release. Permissions and access rights are collected on the schedule configured for each source group. + +--- + +## Compliance continuity + +Historical audit records in the SQL Server database remain intact and queryable regardless of what you do in AA26. There is no gap in the audit record for the period covered by the legacy system. + +For any source that moves to AA26, document the date AA26 began collecting data for it and communicate that boundary to your compliance and legal teams. This ensures that audit requests spanning the transition can be answered by querying the correct system. + +| Data | Source of Record | +| --- | --- | +| Records collected before a source moved to AA26 | Legacy NAA SQL Server database | +| Records collected after a source moved to AA26 | Access Analyzer 26 (ClickHouse) | +| Records for sources still managed by the legacy product | Legacy NAA SQL Server database | + +Where both systems are actively collecting — during a period of incremental adoption — each system is the source of record for the sources it manages. + +--- + +## Related links + +- [Migration Overview](./index.md) +- [Migration Checklist](./migration-checklist.md) +- [Migrating Target Servers and Host Lists](./migrate-target-servers.md) diff --git a/docs/kb/accessanalyzer-2601/migration/index.md b/docs/kb/accessanalyzer-2601/migration/index.md new file mode 100644 index 0000000000..441d52ad44 --- /dev/null +++ b/docs/kb/accessanalyzer-2601/migration/index.md @@ -0,0 +1,107 @@ +--- +title: "Deploying Access Analyzer 26 Alongside Netwrix Access Analyzer" +description: "Concept mapping, adoption guidance, and step-by-step procedures for deploying Access Analyzer 26 in environments running Netwrix Access Analyzer (formerly StealthAUDIT)" +keywords: + - access analyzer migration + - stealthaudit migration + - migrate to AA26 + - host list migration + - connection profile migration + - schedule migration + - sql server audit data + - migration guide + - AA26 adoption +products: + - access-analyzer +sidebar_label: "Migration Overview" +tags: + - migration +--- + +# Deploying Access Analyzer 26 Alongside Netwrix Access Analyzer + +This guide covers deploying Access Analyzer 26 (AA26) in environments where Netwrix Access Analyzer 11.6 or 12.0 (formerly StealthAUDIT) is already running. It is written for Netwrix Professional Services engineers and partners. + +**AA26 and the legacy product run independently and can coexist in the same environment.** Most customers adopt AA26 incrementally — starting with a specific connector type, a set of hosts, a business unit, or a single data center — while the legacy product continues operating normally everywhere else. There is no requirement to move everything at once, and no requirement to decommission the legacy system on any particular timeline. + +These articles provide step-by-step procedures and PowerShell scripts for each adoption phase. Apply them to whatever scope is right for your customer. + +--- + +## What this guide covers + +| Topic | Article | +| --- | --- | +| Migrating target servers and host lists to source groups | [Migrating Target Servers and Host Lists](./migrate-target-servers.md) | +| Migrating connection profiles to service accounts | [Migrating Connection Profiles](./migrate-credentials.md) | +| Migrating job schedules to scan schedules | [Migrating Job Schedules](./migrate-schedules.md) | +| Handling historical audit data during and after migration | [Historical Audit Data Strategy](./audit-data-strategy.md) | +| Pre-migration and post-migration validation checklist | [Migration Checklist](./migration-checklist.md) | + +--- + +## Concept mapping + +Use this table as a quick reference throughout the migration. Each legacy concept maps to its AA26 equivalent. + +| Legacy Concept | AA26 Equivalent | Key Difference | +| --- | --- | --- | +| **Host** | **Source** | A single target system in both products. In AA26, sources belong to a source group. | +| **Host List** | **Source Group** | A source group contains sources of a single connector type. Legacy host lists often contain mixed types and must be split. | +| **Connection Profile** | **Service Account** | AA26 never stores plaintext credentials. Passwords must be re-entered — they can't be exported from the legacy system. | +| **Job / Data Collector** | **Scan** | Scans replace the job/query model. Each source has one scan per scan type (access or sensitive data). | +| **Schedule / Trigger** | **Scan Schedule (cron)** | AA26 uses standard five-field cron expressions. Windows Task Scheduler triggers must be translated to cron. | +| **Proxy Server / Applet** | **Scanner** | AA26 scanners deploy on demand as Kubernetes containers. No manual applet deployment is required. | +| **Storage Profile (SQL Server)** | **ClickHouse + PostgreSQL** | AA26 uses a different database stack. Historical audit data collected by the legacy product remains in the SQL Server database. | +| **FSActivity / ADActivity tables** | *(no current equivalent)* | Historical activity records stay in SQL Server. AA26 collects new activity going forward. | + +--- + +## Scoping your AA26 deployment + +AA26 is designed to address specific gaps or pain points — whether that's better visibility into a particular data source type, coverage for a new cloud environment, or improved sensitive data discovery in a specific region. Common adoption patterns: + +- **By connector type** — Deploy AA26 for Active Directory or Entra ID sources first, while continuing to collect file system data in the legacy product. +- **By site or data center** — Bring one site into AA26 at a time. Other sites continue running under legacy jobs until you're ready to expand. +- **By business unit** — Start with a subset of the environment owned by one team. Validate results, build confidence, then expand to additional groups. +- **Full scope** — Some customers move everything at once, particularly when the legacy system has reached end of support or is being decommissioned. + +The procedures in these articles work the same regardless of scope. Work through the steps for the portion of the environment you're adding to AA26, and repeat them as you expand coverage. + +--- + +## Important constraint: host lists and source types + +In the legacy product, a single host list can contain any mix of target types — Active Directory domain controllers, file servers, and SQL servers can all exist in the same list. + +**AA26 source groups are single-type.** Each source group is created for exactly one connector type, and that type can't be changed after creation. When migrating host lists, you must group targets by connector type and create a separate source group for each type. + +For example, a legacy host list named "Remote Sites" containing Windows file servers and Active Directory domain controllers becomes two AA26 source groups: + +- **Remote Sites — File Servers** (File Server source group) +- **Remote Sites — Active Directory** (Active Directory source group) + +Plan your source group structure before beginning the migration. + +--- + +## What stays in the SQL Server database + +Historical audit records collected by the legacy product — file system activity, Active Directory changes, mailbox activity, sensitive data findings, and all other job output — remain in the SQL Server database. No migration of this data to AA26 is performed as part of this procedure. + +Access Analyzer 26 collects new activity going forward from its cutover date. Historical records in SQL Server remain accessible for audit and compliance purposes by querying the database directly. + +See [Historical Audit Data Strategy](./audit-data-strategy.md) for guidance on maintaining access to these records. + +--- + +## Deployment sequence + +For each scope of the environment you're adding to AA26, work through these steps in order. Each step builds on the previous one. Repeat the sequence for each additional scope you bring into AA26. + +1. **Plan** — Complete the planning section of the [Migration Checklist](./migration-checklist.md). Document the legacy host lists, connection profiles, and schedules that correspond to the scope you're working on. +2. **Set up credentials** — Create service accounts in AA26 for the connector types in scope. The source group wizard requires a service account before you can create a group. +3. **Set up sources** — Create source groups and add sources for each connector type in scope. +4. **Set up schedules** — Configure scan schedules on each source group. +5. **Validate** — Run test connections and an initial scan on each source group. Compare scan results against legacy job output for the same hosts. +6. **Parallel operation** — Both products collect data for their respective scopes. Decide when — or whether — to stop the corresponding legacy jobs for the hosts now covered by AA26. diff --git a/docs/kb/accessanalyzer-2601/migration/migrate-credentials.md b/docs/kb/accessanalyzer-2601/migration/migrate-credentials.md new file mode 100644 index 0000000000..6138636a07 --- /dev/null +++ b/docs/kb/accessanalyzer-2601/migration/migrate-credentials.md @@ -0,0 +1,237 @@ +--- +title: "Migrating Connection Profiles to Service Accounts" +description: "How to inventory legacy Netwrix Access Analyzer connection profiles and recreate them as service accounts in Access Analyzer 26" +keywords: + - connection profile migration + - service account migration + - stealthaudit credentials + - access analyzer credentials + - username password service account + - client id secret + - client certificate +products: + - access-analyzer +sidebar_label: "Migrating Connection Profiles" +tags: + - migration + - service-accounts +--- + +# Migrating Connection Profiles to Service Accounts + +## Overview + +Legacy Netwrix Access Analyzer (StealthAUDIT) stores authentication credentials in **Connection Profiles**. Access Analyzer 26 uses **Service Accounts** for the same purpose. This article explains how to inventory your existing connection profiles and recreate them as service accounts in AA26. + +:::warning +Passwords and client secrets cannot be exported from the legacy system. You must re-enter all credentials when creating service accounts in AA26. Prepare the necessary credentials before starting this procedure. +::: + +--- + +## Credential type mapping + +Each legacy connection profile credential type maps to an AA26 service account type as follows: + +| Legacy Credential Type | AA26 Service Account Type | Used For | +| --- | --- | --- | +| Local machine account (Windows) | Username/Password | File Server sources | +| Active Directory domain account | Username/Password | Active Directory and File Server sources | +| Microsoft Entra ID key | Client ID/Secret | Entra ID sources | +| Web service (certificate) | Client ID/Certificate | SharePoint Online sources | +| Unix account | *(not applicable)* | Not supported in AA26 connectors | +| SQL account | *(not applicable)* | Not supported in AA26 connectors | + +Only the four credential types listed as applicable are needed for the connectors supported in AA26. If your legacy environment uses connection profiles for other purposes (SQL Server inventory, Unix auditing), those do not require migration. + +--- + +## Before you begin + +- Identify all connection profiles used by Active Directory, file server, SharePoint, and Entra ID jobs in the legacy system. +- Obtain the credentials for each profile: username and password for domain accounts, client ID and secret for Entra ID registrations, and client ID and certificate for SharePoint. +- Confirm that each account has the required permissions for its connector type in AA26. See the connector-specific prerequisites in the Access Analyzer documentation. + +--- + +## Step 1 — Inventory legacy connection profiles + +Before creating service accounts in AA26, document every connection profile that needs to be migrated. + +### Export using PowerShell + +The following script queries the legacy NAA SQL Server database to list all connection profiles. Run it on a machine with access to the legacy NAA SQL Server. + +```powershell +<# +.SYNOPSIS + Exports connection profile names and types from the legacy NAA SQL Server database. + Use this output to plan service account creation in AA26. + +.PARAMETER SqlServer + Hostname or IP address of the legacy NAA SQL Server instance. + +.PARAMETER Database + Name of the legacy NAA database (default: StealthAUDIT). + +.EXAMPLE + .\Export-LegacyConnectionProfiles.ps1 -SqlServer "sql01.corp.local" -Database "StealthAUDIT" +#> + +param( + [Parameter(Mandatory)] + [string]$SqlServer, + + [string]$Database = 'StealthAUDIT' +) + +$ErrorActionPreference = 'Stop' + +Write-Host "Connecting to $SqlServer\$Database ..." -ForegroundColor Cyan + +try { + $conn = New-Object System.Data.SqlClient.SqlConnection + $conn.ConnectionString = "Server=$SqlServer;Database=$Database;Integrated Security=True;" + $conn.Open() + + # Query connection profiles table. + # Verify the table name against your database using: + # SELECT name FROM sys.tables WHERE name LIKE '%Profile%' OR name LIKE '%Connection%' + $query = @" +SELECT + cp.ProfileName, + cp.ProfileType, + cp.Username, + cp.Domain, + cp.Notes, + cp.CreatedDate, + cp.ModifiedDate +FROM + SA_ConnectionProfiles cp +ORDER BY + cp.ProfileName +"@ + + $cmd = New-Object System.Data.SqlClient.SqlCommand($query, $conn) + $reader = $cmd.ExecuteReader() + + $profiles = @() + while ($reader.Read()) { + $profiles += [PSCustomObject]@{ + ProfileName = $reader['ProfileName'] + ProfileType = $reader['ProfileType'] + Username = $reader['Username'] + Domain = $reader['Domain'] + Notes = $reader['Notes'] + CreatedDate = $reader['CreatedDate'] + ModifiedDate = $reader['ModifiedDate'] + } + } + $reader.Close() + $conn.Close() + + if ($profiles.Count -eq 0) { + Write-Host "No connection profiles found. Verify the table name in your environment." -ForegroundColor Yellow + } else { + Write-Host "`nFound $($profiles.Count) connection profile(s):" -ForegroundColor Green + $profiles | Format-Table -AutoSize + + $outputPath = ".\LegacyConnectionProfiles_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv" + $profiles | Export-Csv -Path $outputPath -NoTypeInformation + Write-Host "`nExported to: $outputPath" -ForegroundColor Green + Write-Host "`nNEXT STEP: Review the exported file and note which profiles need to be recreated in AA26." -ForegroundColor Cyan + } +} +catch { + Write-Host "Error: $_" -ForegroundColor Red + Write-Host @" + +If the query fails with 'Invalid object name', the table name may differ in your environment. +Run this query to find the correct table: + SELECT name FROM sys.tables WHERE name LIKE '%Profile%' OR name LIKE '%Connection%' +"@ -ForegroundColor Yellow +} +``` + +:::note +The exact SQL table name for connection profiles might differ between NAA versions. If `SA_ConnectionProfiles` does not exist in your database, run `SELECT name FROM sys.tables WHERE name LIKE '%Profile%' OR name LIKE '%Connection%'` to locate the correct table. +::: + +### Export manually from the NAA console + +If direct SQL access is unavailable, document connection profiles from the NAA console: + +1. Open the Netwrix Access Analyzer console. +2. Navigate to **Settings** > **Connection**. +3. Review each connection profile listed. Record the profile name, credential type, username, and domain. +4. Note which jobs reference each profile (visible in the Job Properties panel for each job). + +--- + +## Step 2 — Create service accounts in Access Analyzer + +Create one service account in AA26 for each legacy connection profile that needs to be migrated. + +Navigate to **Configuration** > **Service Accounts**. + +![Service Accounts list showing existing accounts by name, type, and creation date](/images/accessanalyzer/2601/migration/service-accounts-list.png) + +### Create a Username/Password service account + +Use this type for Active Directory and File Server sources. + +1. Click **Add Service Account**. +2. In the **Name** field, enter a descriptive name that matches or maps to the legacy profile name. +3. From the **Account Type** drop-down, select **Username/Password**. + + ![Add Service Account form showing Username/Password fields: name, account type selector, username, and password](/images/accessanalyzer/2601/migration/add-service-account-username-password.png) + +4. In the **Username** field, enter the domain account in the format `DOMAIN\username` or `username@domain`. +5. In the **Password** field, enter the account password. +6. Click **Add account**. + +### Create a Client ID/Secret service account + +Use this type for Entra ID sources. + +1. Click **Add Service Account**. +2. Enter a **Name**. +3. From the **Account Type** drop-down, select **Client ID/Secret**. + + ![Add Service Account form showing Client ID/Secret fields: name, account type, client ID, and client secret](/images/accessanalyzer/2601/migration/add-service-account-client-secret.png) + +4. Enter the **Client ID** (Application ID) from your Entra ID app registration. +5. Enter the **Client Secret** value. +6. Click **Add account**. + +### Create a Client ID/Certificate service account + +Use this type for SharePoint Online sources. + +1. Click **Add Service Account**. +2. Enter a **Name**. +3. From the **Account Type** drop-down, select **Client ID/Certificate**. + + ![Add Service Account form showing Client ID/Certificate fields: name, account type, client ID, and certificate upload](/images/accessanalyzer/2601/migration/add-service-account-certificate.png) + +4. Enter the **Client ID** (Application ID) from your SharePoint app registration. +5. Upload the certificate file (`.pfx` or `.pem` format). +6. Click **Add account**. + +--- + +## Step 3 — Verify + +After creating all service accounts, verify each one before using it in a source group: + +1. In the service accounts list, locate a newly created account. +2. Click the actions menu and select **Edit**. +3. Confirm the credential type and username display correctly. +4. You'll verify connectivity through the source group's **Test Connection** function in the [next migration step](./migrate-target-servers.md). + +--- + +## Related links + +- [Migrating Target Servers and Host Lists](./migrate-target-servers.md) +- [Migration Checklist](./migration-checklist.md) diff --git a/docs/kb/accessanalyzer-2601/migration/migrate-schedules.md b/docs/kb/accessanalyzer-2601/migration/migrate-schedules.md new file mode 100644 index 0000000000..ef843c7b1b --- /dev/null +++ b/docs/kb/accessanalyzer-2601/migration/migrate-schedules.md @@ -0,0 +1,345 @@ +--- +title: "Migrating Job Schedules to Scan Schedules" +description: "How to translate legacy Netwrix Access Analyzer job schedules to cron expressions and configure scan schedules in Access Analyzer 26" +keywords: + - schedule migration + - job schedule migration + - cron expression + - windows task scheduler migration + - scan schedule AA26 + - stealthaudit schedule +products: + - access-analyzer +sidebar_label: "Migrating Job Schedules" +tags: + - migration + - schedules +--- + +# Migrating Job Schedules to Scan Schedules + +## Overview + +The legacy Netwrix Access Analyzer product schedules data collection jobs using **Windows Task Scheduler** triggers. Each job or job group can have one or more triggers that define when and how often the job runs. + +Access Analyzer 26 schedules scans using **cron expressions** — a standard five-field format used in Unix-based scheduling. This article explains how to inventory legacy job schedules, translate them to cron expressions, and configure scan schedules on your AA26 source groups. + +--- + +## Concept comparison + +| Legacy Concept | AA26 Equivalent | +| --- | --- | +| Schedule / Trigger on a job or job group | Cron expression on a scan configuration | +| Schedule Service Account (Windows Task Scheduler) | Scanner service account (runs the scan) | +| Multiple jobs with individual schedules | One scan schedule per source group (shared across all sources in the group) | +| Daily / Weekly / Monthly trigger | Equivalent cron expression | +| Run As — specific domain account | Service account assigned to the source group | + +In AA26, the scan schedule is set at the source group level and applies to all sources in the group. If you need different schedules for individual sources, override the schedule at the source level after creating the group. + +--- + +## Cron expression reference + +AA26 uses standard five-field cron expressions in UTC by default. Each field controls a time component: + +``` +┌───────── minute (0–59) +│ ┌─────── hour (0–23, UTC) +│ │ ┌───── day of month (1–31) +│ │ │ ┌─── month (1–12) +│ │ │ │ ┌─ day of week (0=Sunday, 6=Saturday) +│ │ │ │ │ +* * * * * +``` + +### Common schedule translations + +| Legacy Trigger | Cron Expression | Description | +| --- | --- | --- | +| Daily at 11:00 PM (local) | `0 23 * * *` | Runs at 23:00 UTC daily. Adjust hour for your timezone. | +| Daily at 2:00 AM | `0 2 * * *` | Runs at 02:00 UTC daily. | +| Daily at 6:00 AM | `0 6 * * *` | Runs at 06:00 UTC daily. | +| Weekly — Sunday at midnight | `0 0 * * 0` | Runs at 00:00 UTC every Sunday. | +| Weekly — Monday at 6:00 AM | `0 6 * * 1` | Runs at 06:00 UTC every Monday. | +| Weekly — Saturday at 11:00 PM | `0 23 * * 6` | Runs at 23:00 UTC every Saturday. | +| Monthly — 1st of month at midnight | `0 0 1 * *` | Runs at 00:00 UTC on the 1st. | +| Monthly — 15th of month at 3:00 AM | `0 3 15 * *` | Runs at 03:00 UTC on the 15th. | +| Every 6 hours | `0 */6 * * *` | Runs at 00:00, 06:00, 12:00, 18:00 UTC. | +| Every 12 hours | `0 */12 * * *` | Runs at 00:00 and 12:00 UTC daily. | + +:::note +AA26 stores cron schedules in UTC. If your legacy jobs used local time triggers, convert them to UTC when creating the cron expression. Set the **Time Zone** field on the scan configuration if you want to define the schedule in local time. +::: + +--- + +## Before you begin + +- [ ] Source groups and sources have been created in AA26 ([Migrating Target Servers and Host Lists](./migrate-target-servers.md)). +- [ ] You have a documented list of legacy job schedules (from Step 1 below). +- [ ] You have determined which cron expressions to use for each source group. + +--- + +## Step 1 — Inventory legacy job schedules + +### Option A — Export using PowerShell + +The following script reads scheduled tasks from the Windows Task Scheduler on the legacy NAA console server. Run it on the NAA console server itself or a machine with remote Task Scheduler access. + +```powershell +<# +.SYNOPSIS + Exports all scheduled tasks associated with Netwrix Access Analyzer jobs. + Run this on the NAA console server. + +.PARAMETER ComputerName + Name of the NAA console server. Leave blank to run locally. + +.EXAMPLE + .\Export-LegacySchedules.ps1 + .\Export-LegacySchedules.ps1 -ComputerName "naa-console01.corp.local" +#> + +param( + [string]$ComputerName = $env:COMPUTERNAME +) + +$ErrorActionPreference = 'Stop' + +Write-Host "Reading scheduled tasks from: $ComputerName" -ForegroundColor Cyan + +try { + # Get all tasks — filter to ones that look like NAA job schedules. + # NAA typically creates tasks under a specific folder path; adjust the filter + # below if your installation uses a custom task folder. + $tasks = Get-ScheduledTask -CimSession $ComputerName -ErrorAction Stop | + Where-Object { $_.TaskPath -like '\*StealthAUDIT*' -or + $_.TaskPath -like '\*AccessAnalyzer*' -or + $_.TaskPath -like '\*Netwrix*' } + + if ($tasks.Count -eq 0) { + Write-Host "No NAA-related tasks found under standard paths." -ForegroundColor Yellow + Write-Host "Listing ALL scheduled tasks so you can identify relevant ones:" -ForegroundColor Yellow + $tasks = Get-ScheduledTask -CimSession $ComputerName + } + + $scheduleData = foreach ($task in $tasks) { + $taskInfo = Get-ScheduledTaskInfo -CimSession $ComputerName -TaskPath $task.TaskPath -TaskName $task.TaskName -ErrorAction SilentlyContinue + + foreach ($trigger in $task.Triggers) { + [PSCustomObject]@{ + TaskPath = $task.TaskPath + TaskName = $task.TaskName + State = $task.State + TriggerType = $trigger.CimClass.CimClassName + StartBoundary = $trigger.StartBoundary + RepetitionInterval = $trigger.Repetition.Interval + DaysOfWeek = $trigger.DaysOfWeek + DaysInterval = $trigger.DaysInterval + WeeksInterval = $trigger.WeeksInterval + LastRunTime = $taskInfo.LastRunTime + NextRunTime = $taskInfo.NextRunTime + LastResult = $taskInfo.LastTaskResult + } + } + } + + Write-Host "Found $($scheduleData.Count) trigger(s) across $($tasks.Count) task(s)." -ForegroundColor Green + $scheduleData | Format-Table TaskName, TriggerType, StartBoundary, RepetitionInterval -AutoSize + + $outputPath = ".\LegacySchedules_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv" + $scheduleData | Export-Csv -Path $outputPath -NoTypeInformation + Write-Host "`nExported to: $outputPath" -ForegroundColor Green + + Write-Host @" + +NEXT STEPS: + 1. Open the exported CSV and review trigger types and frequencies. + 2. Use the cron expression reference table in this article to translate each trigger. + 3. Note the cron expression for each source group. + 4. Proceed to Step 2 to configure schedules in AA26. +"@ -ForegroundColor Cyan +} +catch { + Write-Host "Error reading scheduled tasks: $_" -ForegroundColor Red + Write-Host "Ensure you have administrator rights on the target computer." -ForegroundColor Yellow +} +``` + +### Option B — Review manually from the NAA console + +1. In the NAA console, navigate to the **Schedule** node in the left panel. +2. Review each scheduled task listed. For each task, record: + - The job or job group it runs. + - The trigger type (daily, weekly, monthly). + - The start time and recurrence settings. +3. Use the cron expression table above to determine the equivalent for each. + +--- + +## Step 2 — Configure scan schedules in Access Analyzer + +Scan schedules are configured on source groups. Navigate to **Configuration** > **Source Groups**, then edit the group or configure schedules during source group creation. + +![Source group creation wizard step 3 showing scan type selection and cron schedule configuration fields](/images/accessanalyzer/2601/migration/create-source-group-scan-config.png) + +For each source group: + +1. In the source groups list, click the actions menu for the group and select **Edit**. +2. Navigate to the **Scan Configuration** section. +3. Enter the cron expression for the schedule you determined in Step 1. +4. Set the **Time Zone** if you want to express the schedule in local time rather than UTC. +5. Enable the schedule by setting **Schedule Enabled** to active. +6. Click **Save**. + +:::note +If different legacy jobs targeting the same set of hosts had different schedules, you might need to split those hosts across separate source groups in AA26 so each group can have its own schedule. +::: + +--- + +## Step 3 — Apply schedules using PowerShell + +The following script reads a prepared schedule mapping file and applies cron expressions to existing source groups via the AA26 API. + +```powershell +<# +.SYNOPSIS + Applies cron schedules to AA26 source group scan configurations. + Before running, prepare a CSV file (ScheduleMapping.csv) with columns: + SourceGroupId, ScanType, CronExpression, TimeZone + + Example CSV row: + a1b2c3d4-...,access_scan,"0 2 * * *",America/New_York + +.PARAMETER AA26BaseUrl + Base URL of your AA26 instance. + +.PARAMETER AA26Email + Email address of an AA26 administrator account. + +.PARAMETER MappingCsvPath + Path to the schedule mapping CSV file. + +.EXAMPLE + .\Set-AA26ScanSchedules.ps1 ` + -AA26BaseUrl "https://aa26.corp.local" ` + -AA26Email "admin@corp.local" ` + -MappingCsvPath ".\ScheduleMapping.csv" +#> + +param( + [Parameter(Mandatory)] [string]$AA26BaseUrl, + [Parameter(Mandatory)] [string]$AA26Email, + [Parameter(Mandatory)] [string]$MappingCsvPath +) + +$ErrorActionPreference = 'Stop' + +# ── AUTHENTICATE ────────────────────────────────────────────────────────────── +Write-Host "Authenticating to AA26 ..." -ForegroundColor Cyan +$AA26Password = Read-Host "Enter AA26 password for $AA26Email" -AsSecureString +$plainPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto( + [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($AA26Password) +) + +$loginBody = "email=$([Uri]::EscapeDataString($AA26Email))&password=$([Uri]::EscapeDataString($plainPassword))" +$session = New-Object Microsoft.PowerShell.Commands.WebRequestSession + +try { + Invoke-WebRequest -Uri "$AA26BaseUrl/login" -Method POST -Body $loginBody ` + -ContentType 'application/x-www-form-urlencoded' -WebSession $session ` + -MaximumRedirection 5 | Out-Null + $plainPassword = $null + Write-Host "Authenticated." -ForegroundColor Green +} +catch { + Write-Host "Authentication failed: $_" -ForegroundColor Red; exit 1 +} + +# ── LOAD SCHEDULE MAPPING ───────────────────────────────────────────────────── +$mappings = Import-Csv -Path $MappingCsvPath +Write-Host "`nLoaded $($mappings.Count) schedule mapping(s) from $MappingCsvPath" -ForegroundColor Cyan +$mappings | Format-Table -AutoSize + +$confirm = Read-Host "`nApply these schedules? (yes/no)" +if ($confirm -ne 'yes') { Write-Host "Aborted."; exit 0 } + +# ── GET EXISTING SCAN CONFIGS ───────────────────────────────────────────────── +Write-Host "`nFetching existing source groups ..." -ForegroundColor Cyan +$sourceGroups = Invoke-RestMethod -Uri "$AA26BaseUrl/api/v1/source-groups" -Method GET -WebSession $session + +$updated = 0 +$failed = 0 +$errors = @() + +foreach ($mapping in $mappings) { + $groupId = $mapping.SourceGroupId + $scanType = $mapping.ScanType + $cron = $mapping.CronExpression + $tz = $mapping.TimeZone + + Write-Host "`nProcessing group $groupId ($scanType) → cron: '$cron' tz: '$tz'" -ForegroundColor Cyan + + try { + # Get scan configs for this group + $scanConfigs = Invoke-RestMethod ` + -Uri "$AA26BaseUrl/api/v1/source-groups/$groupId/scan-configs" ` + -Method GET ` + -WebSession $session + + $existing = $scanConfigs | Where-Object { $_.scanType -eq $scanType } + + $scheduleBody = @{ + cron_expression = $cron + cron_enabled = $true + cron_time_zone = if ($tz) { $tz } else { 'UTC' } + } | ConvertTo-Json + + if ($existing) { + # Update existing scan config + Invoke-RestMethod -Uri "$AA26BaseUrl/api/v1/source-groups/$groupId/scan-configs/$($existing.id)" ` + -Method PATCH -Body $scheduleBody -ContentType 'application/json' -WebSession $session | Out-Null + Write-Host " [OK] Updated schedule on existing config." -ForegroundColor Green + } else { + # Create new scan config + $newConfig = @{ + scan_type = $scanType + cron_expression = $cron + cron_enabled = $true + cron_time_zone = if ($tz) { $tz } else { 'UTC' } + } | ConvertTo-Json + + Invoke-RestMethod -Uri "$AA26BaseUrl/api/v1/source-groups/$groupId/scan-configs" ` + -Method POST -Body $newConfig -ContentType 'application/json' -WebSession $session | Out-Null + Write-Host " [OK] Created new scan config." -ForegroundColor Green + } + $updated++ + } + catch { + Write-Host " [FAIL] $_" -ForegroundColor Red + $errors += [PSCustomObject]@{ GroupId = $groupId; ScanType = $scanType; Error = $_.ToString() } + $failed++ + } +} + +Write-Host "`n── Schedule Update Summary ─────────────────────────────────────" -ForegroundColor Cyan +Write-Host " Updated : $updated" -ForegroundColor Green +Write-Host " Failed : $failed" -ForegroundColor $(if ($failed -gt 0) { 'Red' } else { 'Green' }) + +if ($errors.Count -gt 0) { + $errPath = ".\ScheduleErrors_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv" + $errors | Export-Csv -Path $errPath -NoTypeInformation + Write-Host "Errors exported to: $errPath" -ForegroundColor Yellow +} +``` + +--- + +## Related links + +- [Migrating Target Servers and Host Lists](./migrate-target-servers.md) +- [Migration Checklist](./migration-checklist.md) diff --git a/docs/kb/accessanalyzer-2601/migration/migrate-target-servers.md b/docs/kb/accessanalyzer-2601/migration/migrate-target-servers.md new file mode 100644 index 0000000000..4cef1e046b --- /dev/null +++ b/docs/kb/accessanalyzer-2601/migration/migrate-target-servers.md @@ -0,0 +1,417 @@ +--- +title: "Migrating Target Servers and Host Lists to Source Groups" +description: "How to inventory legacy Netwrix Access Analyzer host lists and recreate them as source groups and sources in Access Analyzer 26" +keywords: + - host list migration + - source group migration + - migrate hosts to AA26 + - stealthaudit host list + - access analyzer source groups + - target server migration +products: + - access-analyzer +sidebar_label: "Migrating Target Servers and Host Lists" +tags: + - migration + - source-groups +--- + +# Migrating Target Servers and Host Lists to Source Groups + +## Overview + +The legacy Netwrix Access Analyzer product organizes target systems as **Hosts** grouped into **Host Lists**. Access Analyzer 26 uses **Sources** organized into **Source Groups**. This article explains how to inventory your legacy host lists and recreate them as source groups and sources in AA26. + +Before starting this procedure, complete [Migrating Connection Profiles to Service Accounts](./migrate-credentials.md). The source group creation wizard requires a service account, and the account must exist before you create the group. + +--- + +## Key difference: host lists vs. source groups + +In the legacy product, a single host list can contain any mix of target system types. A list named "East Coast Servers" might include file servers, Active Directory domain controllers, and SharePoint sites. + +**AA26 source groups are single-type.** Each group is created for one connector type, and that type is permanent — it can't be changed after creation. You must split mixed-type host lists into separate source groups before you begin. + +**Planning example:** + +| Legacy Host List | Hosts | AA26 Source Groups | +| --- | --- | --- | +| East Coast Servers | 12 file servers, 2 AD domains | East Coast — File Servers (12 sources)
East Coast — Active Directory (2 sources) | +| Cloud Resources | Entra ID tenant, SharePoint site | Cloud — Entra ID (1 source)
Cloud — SharePoint Online (1 source) | + +Plan your source group structure on paper before creating anything in AA26. + +--- + +## Supported connector types + +AA26 currently supports the following connector types. Only hosts of these types need to be migrated: + +| Legacy Collector / Target Type | AA26 Connector | +| --- | --- | +| File System (FSAA) — Windows file servers | File Server | +| File System (FSAA) — NetApp ONTAP | File Server | +| File System (FSAA) — Isilon/PowerScale | File Server | +| File System (FSAA) — Dell VNX, Celerra, Unity | File Server | +| AD Inventory / ADActivity — Active Directory | Active Directory | +| Azure AD / Entra ID | Entra ID | +| SPAA — SharePoint Online | SharePoint Online | + +Legacy jobs targeting SQL Server, Exchange, Unix, or other systems do not have corresponding connectors in AA26 at this time. Document those targets separately for future migration phases. + +--- + +## Before you begin + +- [ ] All service accounts have been created in AA26 ([Migrating Connection Profiles](./migrate-credentials.md)). +- [ ] Scanners have been deployed for Active Directory and File Server source groups. See the scanner deployment documentation in the Access Analyzer product docs. +- [ ] You have a written inventory of host lists and their members (see Step 1). +- [ ] You have planned which legacy host lists map to which AA26 source groups. + +--- + +## Step 1 — Inventory legacy host lists + +Export a complete inventory of your legacy host lists and hosts before making any changes. + +### Option A — Export using PowerShell (recommended) + +The following script queries the legacy NAA SQL Server database to export all host lists and their members. Run it on a machine with access to the legacy SQL Server. + +```powershell +<# +.SYNOPSIS + Exports all host lists and their member hosts from the legacy NAA SQL Server database. + Use this output to plan source group creation in AA26. + +.PARAMETER SqlServer + Hostname or IP address of the legacy NAA SQL Server. + +.PARAMETER Database + Name of the legacy NAA database (default: StealthAUDIT). + +.EXAMPLE + .\Export-LegacyHostLists.ps1 -SqlServer "sql01.corp.local" -Database "StealthAUDIT" +#> + +param( + [Parameter(Mandatory)] + [string]$SqlServer, + + [string]$Database = 'StealthAUDIT' +) + +$ErrorActionPreference = 'Stop' + +Write-Host "Connecting to $SqlServer\$Database ..." -ForegroundColor Cyan + +try { + $conn = New-Object System.Data.SqlClient.SqlConnection + $conn.ConnectionString = "Server=$SqlServer;Database=$Database;Integrated Security=True;" + $conn.Open() + + # CHECKPOINT: Verify host list table names before running. + # Run this query first to confirm the table names in your environment: + # SELECT name FROM sys.tables WHERE name LIKE '%Host%' ORDER BY name + # + # Common table names in NAA 11.6 and 12.0: + # SA_HostMaster - all registered hosts (hostname, OS, IP, domain) + # SA_HostLists - host list definitions (name, type, description) + # SA_HostListMembers - junction table linking hosts to host lists + + $query = @" +SELECT + hl.HostListName, + hl.HostListType, + hl.Description AS ListDescription, + h.HostName, + h.DNSName, + h.IPAddress, + h.OperatingSystem, + h.Domain, + h.OSType +FROM + SA_HostLists hl + JOIN SA_HostListMembers hlm ON hl.HostListID = hlm.HostListID + JOIN SA_HostMaster h ON hlm.HostID = h.HostID +ORDER BY + hl.HostListName, + h.HostName +"@ + + $cmd = New-Object System.Data.SqlClient.SqlCommand($query, $conn) + $reader = $cmd.ExecuteReader() + + $results = @() + while ($reader.Read()) { + $results += [PSCustomObject]@{ + HostListName = $reader['HostListName'] + HostListType = $reader['HostListType'] + ListDesc = $reader['ListDescription'] + HostName = $reader['HostName'] + DNSName = $reader['DNSName'] + IPAddress = $reader['IPAddress'] + OS = $reader['OperatingSystem'] + Domain = $reader['Domain'] + OSType = $reader['OSType'] + } + } + $reader.Close() + $conn.Close() + + Write-Host "Found $($results.Count) host-list entries across $((($results | Select-Object -ExpandProperty HostListName) | Sort-Object -Unique).Count) lists." -ForegroundColor Green + $results | Format-Table -AutoSize + + $outputPath = ".\LegacyHostLists_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv" + $results | Export-Csv -Path $outputPath -NoTypeInformation + Write-Host "`nExported to: $outputPath" -ForegroundColor Green + + Write-Host @" + +NEXT STEPS: + 1. Open the exported CSV. + 2. For each host list, identify what connector type each host requires (File Server, Active Directory, Entra ID, SharePoint). + 3. Group hosts by connector type — this determines your AA26 source groups. + 4. Proceed to Step 2 to create source groups in AA26. +"@ -ForegroundColor Cyan +} +catch { + Write-Host "Error: $_" -ForegroundColor Red + Write-Host @" + +If the query fails with 'Invalid object name', confirm your table names: + Run: SELECT name FROM sys.tables WHERE name LIKE '%Host%' ORDER BY name +Then update the table names in this script accordingly. +"@ -ForegroundColor Yellow +} +``` + +### Option B — Export manually from the NAA console + +1. Open the Netwrix Access Analyzer console. +2. Navigate to **Host Management** in the left panel. +3. For each host list, right-click and select **Export** to export the host list to CSV. +4. Record the host list name, the number of hosts, and the system types present. + +--- + +## Step 2 — Create source groups in Access Analyzer + +Navigate to **Configuration** > **Source Groups**. + +![Source Groups list showing existing groups with source type, service account, scan type, and status columns](/images/accessanalyzer/2601/migration/source-groups-list.png) + +Create one source group for each connector type across your legacy host lists. Click **Create Source Group** to open the wizard. + +### Step 1 of 3 — Select the source type + +The wizard first asks you to choose a connector type. + +![Source group creation wizard step 1 showing four source type options: Active Directory, Entra ID, File Server, and SharePoint Online](/images/accessanalyzer/2601/migration/create-source-group-type-select.png) + +Select the connector type that matches the hosts you are migrating. If you have hosts of multiple types from the same legacy host list, you'll repeat this process for each type. + +### Step 2 of 3 — Configure the group + +![Source group creation wizard step 2 showing name field, service account selection, and max concurrent scans setting for a File Server group](/images/accessanalyzer/2601/migration/create-source-group-file-server.png) + +| Field | What to enter | +| --- | --- | +| **Name** | A descriptive name that identifies the source type and scope. Example: `File Servers — East Coast` | +| **Service Account** | Select the service account you created for this connector type. | +| **Max Concurrent Scans** | Leave at `1` for initial setup. Increase after validating the first scan. | +| **Scanner Labels** | For Active Directory and File Server groups, add labels matching your deployed scanners. | + +Add sources to the group: +- For each host in the matching legacy host list, click **Add Source** and enter the hostname or IP address. +- Use the **Test Connection** button to verify connectivity for each source before saving. + +### Step 3 of 3 — Configure scan parameters + +![Source group creation wizard step 3 showing scan type selection and schedule configuration fields](/images/accessanalyzer/2601/migration/create-source-group-scan-config.png) + +Select the scan types to enable. Configure the scan schedule using a cron expression. See [Migrating Job Schedules](./migrate-schedules.md) for guidance on translating legacy schedule triggers to cron expressions. + +Click **Save** to create the source group. + +--- + +## Step 3 — Import sources using PowerShell + +If you have many hosts to add, the following script reads the CSV exported in Step 1 and creates sources in AA26 via the REST API. Run it source group by source group, after verifying the source group exists in AA26. + +```powershell +<# +.SYNOPSIS + Creates AA26 sources from a legacy host list export CSV for a specified source group. + Run this script once per source group, after the group has been created in the AA26 UI. + +.PARAMETER AA26BaseUrl + Base URL of your AA26 instance. Example: https://aa26.corp.local + +.PARAMETER AA26Email + Email address of an AA26 administrator account. + +.PARAMETER SourceGroupId + The UUID of the target source group in AA26. + Find this in the AA26 URL when viewing a source group, or via GET /api/v1/source-groups. + +.PARAMETER CsvPath + Path to the CSV file exported by Export-LegacyHostLists.ps1. + +.PARAMETER HostListName + Name of the legacy host list to import from the CSV (must match exactly). + +.EXAMPLE + .\Import-AA26Sources.ps1 ` + -AA26BaseUrl "https://aa26.corp.local" ` + -AA26Email "admin@corp.local" ` + -SourceGroupId "a1b2c3d4-e5f6-7890-abcd-ef1234567890" ` + -CsvPath ".\LegacyHostLists_20240414.csv" ` + -HostListName "East Coast File Servers" +#> + +param( + [Parameter(Mandatory)] [string]$AA26BaseUrl, + [Parameter(Mandatory)] [string]$AA26Email, + [Parameter(Mandatory)] [string]$SourceGroupId, + [Parameter(Mandatory)] [string]$CsvPath, + [Parameter(Mandatory)] [string]$HostListName +) + +$ErrorActionPreference = 'Stop' + +# ── AUTHENTICATE ────────────────────────────────────────────────────────────── +Write-Host "Authenticating to AA26 ..." -ForegroundColor Cyan +$AA26Password = Read-Host "Enter AA26 password for $AA26Email" -AsSecureString +$plainPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto( + [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($AA26Password) +) + +# Submit login form and capture session cookie +$loginBody = "email=$([Uri]::EscapeDataString($AA26Email))&password=$([Uri]::EscapeDataString($plainPassword))" +$session = New-Object Microsoft.PowerShell.Commands.WebRequestSession + +try { + $loginResponse = Invoke-WebRequest ` + -Uri "$AA26BaseUrl/login" ` + -Method POST ` + -Body $loginBody ` + -ContentType 'application/x-www-form-urlencoded' ` + -WebSession $session ` + -MaximumRedirection 5 + + $plainPassword = $null # Clear from memory + + if ($session.Cookies.Count -eq 0) { + throw "Login may have failed — no session cookie received. Verify credentials and the login endpoint." + } + Write-Host "Authenticated successfully." -ForegroundColor Green +} +catch { + Write-Host "Authentication failed: $_" -ForegroundColor Red + Write-Host "Verify the AA26 base URL and credentials, then retry." -ForegroundColor Yellow + exit 1 +} + +# ── LOAD HOST LIST FROM CSV ─────────────────────────────────────────────────── +Write-Host "`nLoading host list '$HostListName' from $CsvPath ..." -ForegroundColor Cyan + +$allHosts = Import-Csv -Path $CsvPath +$targetList = $allHosts | Where-Object { $_.HostListName -eq $HostListName } + +if ($targetList.Count -eq 0) { + Write-Host "No hosts found for host list '$HostListName'. Check the HostListName value and retry." -ForegroundColor Red + exit 1 +} + +Write-Host "Found $($targetList.Count) host(s) in list '$HostListName'." -ForegroundColor Green +$targetList | Select-Object HostName, DNSName, IPAddress, OS | Format-Table -AutoSize + +# CHECKPOINT +Write-Host "`nReview the host list above." -ForegroundColor Yellow +$confirm = Read-Host "Proceed with adding these hosts to source group '$SourceGroupId'? (yes/no)" +if ($confirm -ne 'yes') { Write-Host "Aborted."; exit 0 } + +# ── ADD SOURCES TO SOURCE GROUP ─────────────────────────────────────────────── +$created = 0 +$failed = 0 +$errors = @() + +foreach ($h in $targetList) { + $hostName = if ($h.DNSName) { $h.DNSName } else { $h.HostName } + + $sourceBody = @{ + name = $h.HostName + source_group_id = $SourceGroupId + connection_parameters = @{ + host = $hostName + } + } | ConvertTo-Json -Depth 5 + + try { + $response = Invoke-RestMethod ` + -Uri "$AA26BaseUrl/api/v1/sources" ` + -Method POST ` + -Body $sourceBody ` + -ContentType 'application/json' ` + -WebSession $session + + Write-Host " [OK] Added: $($h.HostName) ($hostName)" -ForegroundColor Green + $created++ + } + catch { + Write-Host " [FAIL] $($h.HostName): $_" -ForegroundColor Red + $errors += [PSCustomObject]@{ HostName = $h.HostName; Error = $_.ToString() } + $failed++ + } +} + +# ── SUMMARY ─────────────────────────────────────────────────────────────────── +Write-Host "`n── Import Summary ──────────────────────────────────────────────" -ForegroundColor Cyan +Write-Host " Created : $created" -ForegroundColor Green +Write-Host " Failed : $failed" -ForegroundColor $(if ($failed -gt 0) { 'Red' } else { 'Green' }) + +if ($errors.Count -gt 0) { + $errorPath = ".\ImportErrors_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv" + $errors | Export-Csv -Path $errorPath -NoTypeInformation + Write-Host "`nErrors exported to: $errorPath" -ForegroundColor Yellow + Write-Host "Review and resolve errors, then re-run for failed hosts only." -ForegroundColor Yellow +} + +Write-Host @" + +NEXT STEPS: + 1. In AA26, open the source group and verify each source is listed. + 2. Click Test Connection on each source to validate connectivity. + 3. Proceed to configure scan schedules: Migrating Job Schedules. +"@ -ForegroundColor Cyan +``` + +:::note +The `connection_parameters` structure in the API call varies by connector type. The example above shows the minimal format for File Server sources. For Active Directory sources, the parameter is typically `domain` rather than `host`. Review the AA26 API documentation at `/api-docs` for connector-specific parameter schemas. +::: + +--- + +## Step 4 — Test connections + +After adding sources, verify that AA26 can reach each target: + +1. Navigate to **Configuration** > **Source Groups**. +2. Click the actions menu for your new source group and select **View Sources**. +3. For each source, click the actions menu and select **Test Connection**. +4. Confirm that all sources show a successful connection result before proceeding. + +If a connection test fails, verify that: +- The service account has the required permissions on the target system. +- The scanner assigned to the source group can reach the target on the required ports. +- The hostname or IP address in the source matches what the scanner can resolve. + +--- + +## Related links + +- [Migrating Connection Profiles](./migrate-credentials.md) +- [Migrating Job Schedules](./migrate-schedules.md) +- [Migration Checklist](./migration-checklist.md) diff --git a/docs/kb/accessanalyzer-2601/migration/migration-checklist.md b/docs/kb/accessanalyzer-2601/migration/migration-checklist.md new file mode 100644 index 0000000000..55e0394414 --- /dev/null +++ b/docs/kb/accessanalyzer-2601/migration/migration-checklist.md @@ -0,0 +1,170 @@ +--- +title: "Migration Checklist" +description: "Pre-migration, in-migration, and post-migration validation checklist for migrating from Netwrix Access Analyzer to Access Analyzer 26" +keywords: + - migration checklist + - access analyzer migration validation + - stealthaudit migration checklist + - pre migration checklist + - post migration validation +products: + - access-analyzer +sidebar_label: "Migration Checklist" +tags: + - migration +--- + +# Migration Checklist + +Use this checklist to plan and track an AA26 deployment. It covers one scope of adoption — a connector type, a site, a set of hosts, or a full environment. If you're adopting AA26 incrementally, complete a separate instance of this checklist for each scope. + +Both AA26 and the legacy product can run simultaneously. There is no requirement to decommission or fully migrate anything as part of this process. + +**Customer:** _____________________________    **Date:** _____________________________ + +**Engineer:** _____________________________    **AA26 version:** _____________________________ + +**Scope of this deployment:** _____________________________ + +--- + +## Pre-migration — Legacy system documentation + +Complete this section before making any changes to either system. + +### Legacy system inventory + +- [ ] Documented all active host lists, including name, description, and member count. +- [ ] Documented the target type of each host in each list (file server, Active Directory, Entra ID, SharePoint Online, other). +- [ ] Exported host list data using `Export-LegacyHostLists.ps1` or manual console export. +- [ ] Identified which host lists contain mixed types and documented the required split into separate source groups. +- [ ] Documented all connection profiles: name, credential type, username/domain. +- [ ] Identified which connection profiles map to which credential type in AA26 (Username/Password, Client ID/Secret, Client ID/Certificate). +- [ ] Noted which legacy jobs are in scope for migration (AD, file server, SharePoint, Entra ID jobs). +- [ ] Noted which legacy jobs are out of scope (SQL Server, Exchange, Unix, and other unsupported connectors). +- [ ] Exported job schedule data using `Export-LegacySchedules.ps1` or manual review. +- [ ] Translated all required schedules to cron expressions. Cron expressions documented: _______________________. + +### Legacy database documentation + +- [ ] Confirmed the SQL Server instance name and database name for the legacy NAA database. +- [ ] Documented the date of the most recent successful job run for each in-scope job. +- [ ] Identified the activity table names for historical data that needs to remain accessible. +- [ ] Confirmed who requires read access to the legacy SQL Server database post-migration. + +### AA26 environment readiness + +- [ ] AA26 instance is deployed and accessible. +- [ ] Administrator account credentials for AA26 are confirmed. +- [ ] Scanners are deployed and online for all required connector types (Active Directory, File Server). +- [ ] Network connectivity is confirmed from scanner to each target system on required ports. +- [ ] Required app registrations in Entra ID / Azure are in place (for Entra ID and SharePoint Online sources). + +--- + +## Migration phase 1 — Credentials + +- [ ] All required Username/Password service accounts created in AA26. + - Count: _____ accounts +- [ ] All required Client ID/Secret service accounts created in AA26. + - Count: _____ accounts +- [ ] All required Client ID/Certificate service accounts created in AA26. + - Count: _____ accounts +- [ ] Each service account verified by visual inspection in the Service Accounts list. + +--- + +## Migration phase 2 — Source groups and sources + +Complete one row per source group. + +| Source Group Name | Connector Type | No. of Sources | Service Account | Test Connection | +| --- | --- | --- | --- | --- | +| | | | | Pass / Fail | +| | | | | Pass / Fail | +| | | | | Pass / Fail | +| | | | | Pass / Fail | +| | | | | Pass / Fail | +| | | | | Pass / Fail | +| | | | | Pass / Fail | +| | | | | Pass / Fail | + +- [ ] All source groups created in AA26. +- [ ] All sources added to their respective groups. +- [ ] Test Connection passed for every source in every group. +- [ ] Scanner labels verified on Active Directory and File Server groups. + +--- + +## Migration phase 3 — Scan schedules + +- [ ] Cron expressions applied to all source groups. +- [ ] Schedule time zones confirmed (UTC or local time as required). +- [ ] Schedules verified as enabled on each source group. + +--- + +## Migration phase 4 — Initial scan validation + +For each source group, run an initial access scan manually before enabling the schedule. + +| Source Group Name | Scan Type | Scan Status | Finding Count | Compared to Legacy | +| --- | --- | --- | --- | --- | +| | Access | | | Match / Difference | +| | Sensitive Data | | | Match / Difference | +| | Access | | | Match / Difference | +| | Sensitive Data | | | Match / Difference | +| | Access | | | Match / Difference | +| | Sensitive Data | | | Match / Difference | + +- [ ] All source groups have completed at least one successful access scan. +- [ ] Scan results reviewed and validated against legacy job output. +- [ ] Significant discrepancies documented and investigated. + +**Discrepancy notes:** _______________________________________________________________________________ + +--- + +## Post-migration + +### Legacy system + +- [ ] Decision made on whether to stop legacy jobs for sources now covered by AA26 *(optional — both systems can run simultaneously)*. +- [ ] If legacy jobs for in-scope sources are being stopped: jobs have been disabled and the date recorded. +- [ ] Read-only SQL Server access confirmed for authorized users (compliance, legal, analysts) who need historical records. +- [ ] Coverage boundary documented per source: _________________________ (date AA26 began collecting for each in-scope source). +- [ ] Compliance and legal teams notified of which system holds records for which sources and time periods. + +### AA26 system + +- [ ] AA26 scheduled scans running on configured cron schedule without errors. +- [ ] No scan execution failures in the first 48 hours of scheduled operation. +- [ ] Users and roles configured for all required analysts and administrators. +- [ ] Dashboards and reports accessible to relevant users. + +### Handover + +- [ ] Migration summary document completed and delivered to customer. +- [ ] Customer IT or security team trained on AA26 source group management. +- [ ] Customer IT or security team trained on interpreting scan results. +- [ ] Support escalation path communicated to customer. + +--- + +## Sign-off + +| Role | Name | Signature | Date | +| --- | --- | --- | --- | +| Migration Engineer | | | | +| Customer IT Lead | | | | +| Customer Security Lead | | | | + +--- + +## Related links + +- [Migration Overview](./index.md) +- [Migrating Connection Profiles](./migrate-credentials.md) +- [Migrating Target Servers and Host Lists](./migrate-target-servers.md) +- [Migrating Job Schedules](./migrate-schedules.md) +- [Historical Audit Data Strategy](./audit-data-strategy.md) diff --git a/static/images/accessanalyzer/2601/migration/_after-login.png b/static/images/accessanalyzer/2601/migration/_after-login.png new file mode 100644 index 0000000000000000000000000000000000000000..811fe27c7a592a07029ec5c5a2b359c852a99959 GIT binary patch literal 72560 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 EFKs*qrvLx| literal 0 HcmV?d00001 diff --git a/static/images/accessanalyzer/2601/migration/_login.png b/static/images/accessanalyzer/2601/migration/_login.png new file mode 100644 index 0000000000000000000000000000000000000000..fa0d3446daad5a9fd2728939e092798fcf3560f4 GIT binary patch literal 15603 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 literal 0 HcmV?d00001 diff --git a/static/images/accessanalyzer/2601/migration/add-service-account-certificate.png b/static/images/accessanalyzer/2601/migration/add-service-account-certificate.png new file mode 100644 index 0000000000000000000000000000000000000000..db8c5cd8e184da643a061ca5d444fed4d432862d GIT binary patch literal 126602 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

5}U!ybHA_T_*oH>^k7%b*& zz>30aNr+wK91^-E`sNLyot<4p)vtq{o!FkfnGtts@$n@nJTU9RONytnRfEj|Oh8Rd z9O(R3JB`3KgfOCvkCcGe6Y>#EFc+4O|;1FxLPtP!o3(D9%rcG3I>1Ayrv<3P=mr zVuS=}1&Ev{2$%zF)L&j@sf{r&iHpPii#txu=NdWVG6#a$@~-poN?oY*;8 zCvK;62cWY9*g{Y>14nN_oh-=bqf+_t%KPdxfsb#!!GEB)?MCo?$=bqTW994i#zA`) zs+3?huYBurZEx3PjH)Aza*G<5CT$X5<5g+ zJiYs_2}Ds*+47GZl*CtD4X=PX9>+(gQ*ZBi@YZ&ik~Wmw2g~Nj0wBYlo;Tx;_aKKk zD%s7oJwotHc~))hbIS5UZ*_ACnm#F+kgfObxFd89u6*@xxA|+%JSk)V;EO0v2nu5Q zf$6Cg9-EE_4govYky>k~Y$6=w;*aJ|$BR#E11b7?d7#<;%op(e{67AIo?g1(rSPi@ zkUC2)r9nchbKLmvCbP>DAf`OFTT~{j41k9j6L+~ss`%i*pnyquw$6Ek#PXDZmDL1n zutbkgp3-<-%M=yh+&8DTWsh$12dl$g@<(=@9(-oWJ1lwP^eavIGHEE-A1e^mbSM&4H9A~Mu3u)RY#D% z@w10m#zNBbW@;Nqv|8_+u7sT5zyrmnvaQ^1ad}&0bTsV?Boz*0Uns!GM|1Dm?CkHO z>%9GIbpuYe-(*5f$GMcR7dw9oMdky-#z2DAVq+3@Pk=AnaC!_t-S`QWS5<-aKUu%m z=86zME3L`p!AqJ8i~b)!)_|~j-QBER?q4~k6tx1`3Qi>Ozbw&^JHoE3^5x;9pzH*= zW1QJ|ug}xHBmi4gy=X9vG;tmCDF57hW1nE_zQbLv)6`&gF%G6IuQ^W?#;2!+p@JK_ zO8c{K`y&%^bEWPpde(4UFZQH@L<1^=DuaT=^&80vAyE zg52=}Tw&KglkX&-JL&L`)92VeoSl=CFJS{24-O9jm_d#@j;bPa{5oW$6}>o_pDZh@ zxu~>-Pz>Izt?kCl-Q1kVseSMl@rOpBjL*)>*VVvHK60!i!bpuAo#UC!oOfMai(MBP z5rxS7HVFqS82_j-sCCcKNa+{eFxZ^pVj5an9P3?RSKCid*DiV68-7{w78w~xhe!VW z5h)1Jr`(oqHSuN=SC#S9@~IAqalt{&MCw352(isbOG`<_soU%h13ma^6LLyxoD)a4 zsCanqD$rymDyW5d0+R70@ZS%Pff(|+zkZNz%PLQyu_N1br@C#lxNL%&GLKdKr`<7bxhgx_pNZ4qL@ZPtZ zw6HK?5ek(R;Ybdb*iBknU-!E!DvG)#gwP#<*w%9SB3Zr9o@`ZcmONyN%;vB>bRcY_ zLDOq%(p6Ckm>X8Z^3xQRl^d*&BXIhL`@hUFu+#5>ouVF^9_L0V6<#JgK5C|)AD3C? zK>tSw13T5XDa9Fah)kbJcq~k$2pRO#jljj=muDP{dYzY{#bT%g_SE4q9I-Mu)4|dz zjfE05^Kzxr%m9pC%dF_*vC zoTZ;fHg;{bK=clb0oK!;b;Q!y&|!MP(}L5k?Zzk}(Gp<0pNm$Zd7($3ZztXFP>?mD zmwcSZ*8npsFeaVi3(lo}v0Mrw2eMNeimTl>_D}NmW#P zl@N?nv?==^%V0G;`B>!&(O2aox`>2_i=m-OzJ(ZMWWA%aWBZ_jV+w+kWpZ+|?rZ`D zI3NM6KS!gyyj&A9Flbq{j<<-Wg=W6@e}`g<&5@9WloR7-d?RF577mGjDS0H?cj$T_ zQ&U&$?DR}bJb_JFd=@itQQu(oLt(H?e3ZQ`sQ z$V#-c5mr-s3Ys*U4-E}f)zqZ+$mI!BILQgQQc|$hir9*!2D4ktI&APk4c4#If3R5IL+X&hgU)${w6U3?jqPHl) zHrD#|^}{XfRZr^3RPWsSX@}5pxGwi@$YBv-TvUmktSrX;s4v$ftQV5@PwFrCPQ!@y zcb4gJ7l;Hu7x){b)mTsn2@@75^1IA3C!_@^mIg`17xEb)D;zv2&?Yi-#^zVT8vOyzX7s# z&%y$U_~3TPp*St$lSB?)a%!$W8_Vnx)}-EW#j&zlZ!V`a3X7G0fe!wXS88hHMufpM zF&n=~ij$7r_SFD&TYsnZGw4x!KwZ^L)V$jTJFK1gEcIh3ih8Y_o4K$)SJT!pChihD zU)fw&{zpC^LWjK0;{_z=t*3;r#6W?XIC60J&opPTJw=bqz5%|TFkV8B+*~ms1X%_u zNGlYSm5q0H9;)8sp6l1dkX5#^q1s_XIt-2Y__6r?a3uI@?s6;iYOr&$p`hPu6neR_ zxyftA_qy~XKR>&Wrm(5d;N=rqTD)fjwz3D(4YtlZwQq+=)&)qWe}A}>C#aE}npb+O zK^MqTMU}$r(PT%&PH<2dEl`(NQqq!_-`-sGq4=yZ6BWUdBydZfQLV%dab}WQHZ5NL z6L3Jm{5)a*Ufl4ZWPtyq+-}s+bPJzl?ZLqjkXRcZHpCMi-lLa_Wq5vb3+64*xh;Ne zS%4+MAWuvZ7(L3$6=wr#Pi)njmQ>l`5F?w&7i;_LBI3I+Gt@sPBqhDpUj)MT?N&&p7ENvu zEI^R9q{RC2(iLti5HD?FOM999xPi=On1P@RwWxC50 zhs{@4Akau24^+c3tMY_K!j-jQA3SfzL6-5-SORv%Fk@n@Y|(W&F+>v2}Sl zr}#_e4|5oP!vTv1#YBKtTUl9I=ZR$+FSGswT&fEMmrD*3&p8L-eVWi3G7Qq$N+XV2 z_QdZZtLefYTV>63_6V8Z$L4iC4fKi3nC{xqyn|$}WsQsK83WKa;{3>JqTflE=jc*i zp$m*Fk#M~Zk7Na|4UPO zdb%{z=v^RpzoI!qIz}}%HrCZM860EYQXPlg1s4}LRl~cnr?WpLy)2~etbd7RgtAp- zI+3W1kL+KwfXuv<6p7DIx#LemLV}m}NsWSGSI_L0J_D}>f{b_z%ktLN*vv>ja4U-L zCIv;6AS4A<;s-JkH|;0Q_&vq}b}(@g92OADv-ktoCFJ;-(+KT0>e` zxu~Skipn*-CD*H~kpc`^2{t1y;qiXQy{6Yg$qv8XbbFH(7lp#zIcXvSqV>Hpl1*%kdxx$N zsJOhss&k!6Ix&|L#%3E~O2jJqI};X?oSVBig=odfON8Sgry=HD{MPZChsXE1r>-v3 zk@`Q2%8P}IbMng&(wT_V>8!0^8PS_(EW<>tCyppc8i07@bn-N3`|qXXcdBjKdI!2F zI0bH%I6Cm0BRVL(9^n9@Dpy%d?68AljqV+0+Q*!zlRsbf{@UDR>R{U3UJnUCY4(iF zFtyOtb@|;!QfC1%5wufcvcEGH%$N1$daes$+dsd|qDlKsKaS@E>BBJfFa6_j0QG>U z-gwtI%?0s9a^QP;39Iyg;^NF$DHD@B<_Ieq)w;MjK^R-S>PiX_3JMsAh$?Xv6H}Jh z!#Dom?EIke^wgQ=?95ZhB*BHvV|$Tv65578 z^z3T^5ki2(pot05U_ma5{*xH*`8iB&XJ;ZDM5qHEuvk%299nl3qRcZB4>R*io}=TV zx_3 z$nBTuT`ys^tZe&tQ150H78IJ?Z$`L}EAOBbR%nD@WQ23k@_gdU(GmP#!%d>>k8SKb z%ea>7cBDv~(dlq5s}pwmakSfullHcmIWuc)!NE(BfIoy*{Jf@LO~dN6v{Xi`%y7{wtJ9d7IbkP8LPIyknPLzW?WqTfl7RQ{1$5A!1;Cg z?_3s3hSaKRs+Co|0dMRv42I-Qs2$HM18+j3ur&%>l?+!Di`BgDLr#HNQ%(7*vYE-r+_5MTqZ{*C`t|;Hs_Uj*8S($ATpWC~R{AWpAUNc+=E%ph9 zk&xiKeshGG1wA`gZs}fMH7jZ}OG=2i5QMxMbu3<$)M)ytsjB}@+?_?NkE$0AzepPQg3S7a|CzZ@eK2Vs+l!CMf46IGeixqg7R{+}LTs(;kP zll19Iulqv-?>Ys^1v;4ESr9G0V}$tFN93eX^Vu_VeeX}d2TpCGV@C>-D;$gls?mN! zgK8Nalrc^fIrg`$;wBhHV(~f?bz?qt^}j7n$7rhOnX zT|A+>{0}n=i`@T3{BZyJX@$tJPda30-aV8sB|pb;*1xKMvd8yYNV=ayA=_7VDWD98 zse_JD(|t*=8CWp zw?EcOU-$eD4HshlKL)x|ArISFE;s*~^%?qaFma(^I6L7eGrs%6hntKUkg8_$($Lv? zbUXOg%bZ-Z7XB?&NbX2lG|p?S0i1ob zp&@0<@S)XHKOdj-Uo%!Oh(bZ`A2fE+<`L303N*aGzOw_ZK5KED4}0*h4P!c-`vw$*fFDycubgIjOaFyPq#FVb=HldfH9@&jY+Dr#xEf+-^l@BE|M9s{ZO~ zXD5l&@mIKYMpD(ajWz`9Z^hFIP6e->)eUOkP>|+c`|@A0?fEMzbj^DQZ`BYi0kV_9QVx)gj(V1x&_Re{WcvShDY5!B8E3{`c0_DAyNPtmeP7 zIB|r^@>TCoMc;`W3KO!oY3V!pU1;Q!z7HTporu zxF&C8VNq6IURGjlXk_$P&k~wTKRzMh`d*Db$YUT;4e0F+&?P`|km8fqdV1C-CJC{b zH3JxiNX?Fu&$LBT!1dHwa4#WGS-+B!Rbf@{94 zEKd3<%sCq1RR5OM85?^L8eabLwu7{$sj9lY{&Yh|lrC4yn)OF`s$M4LwA_=JWcMRY zWrJA!s^wNRFsGp4r4v7Ok+j!`@YB-6=6vI&>@Z#a>rcTcO^zlf_lKG3TN#-G|EJe~ z`Q`e01m$xJi^9kQW8~7g=Qe@yC4 zpTz)z2nKUNR@j-k<9h%(Qcy}|7%Y7s`OS~HsXDRIP zGoKYF%vG=7JpdglDi$8YLnw_Hb@}8;Skz1X!O>B`2Bh$Q%gj6maqP6!V6vt8K`ySJ zm^XYxpx@8E(fKmFvO3}~v7)aJ01e2DfV^vLWX{3D5(iVmVku{5F$ko5x`O}_j>AHY zIx2cTm4OznOV>-FP=Th1@5ul9by-M=^u!@M2gmh8b^S_XIpiTAnIdZkO)%{q8y6S! zI|G$v;TtWCZgm^44agk;16Ylkb!Y z5I5{wk6K0F;ywE=X3@FKk1to)-g&cA9Ml{D%(n|c$R8{z_pp%ee+0D&Yh-X@;H+r` zZOiK)w~OHi+Hp@xkiMOx4qAqWaE@JFFDbjB3dZl;MA-sB;|jf6Ep-hIg?34xcL#Ws zmZDDa@{C~=C*3%_Knsz+CT#imAle(t1VYsU@u1T`-%IgNP7K_jKw1t8u(Pm48~~qJ zGg}d;8!!jji8^AJ14rkMxklCdukLcf_?T;uk*33qV0T?UIdf8e zJq&8CL^J+o5>;;!K=#$tUvVu>K*+%LvetQt-~QWgLLxC+T|BMQnB0$3^{xi&(^IGw zS4M12*w~9NUj}24@P*>J?|K5;z`^Pk!sVVY>p+Qb?a^=W-Z5WkY`ojX*TY`)_s4`d zhOe)vsrCo*v+vz+Smy+B7nPMAx544pz0|6r&~Tp!6mR&%IHY zSJCyIx_}?^xBn-Ii;8)JNlC{5?0ThW2Sv~Ddwwtk2Zc3J|L#dVFSFpQ^AAXbltTdC z9o{0BWeV^06Cy}l&28r8+s-8m@Yp#iC`?&AyHeQl@<_R9ckdo=>MpNpm9#X&!0ovX zkRnglA_fy?EYV036$vR6iwAc(EA5T?DSLb}*zn5sQ zwZ6W6xlr;eK0yuUaS#g4d1BI{h$T^4S}LK}KQ#n}CZIUGpm4VpQ;&JaWv|bDK)CY@G8@DsB+-%&l1yK21;fZ! zmpa`~wZ_fo+Bu(p*m1M{?j{!pn`V(t=!<@3W#wmY_dO{#rI>P=BpFD-Y|3kQz%Dsj z{hO*c5HG*2bR9t;u}Gx$u7lN(`{vRK$)tN$p-BrBhHQm&!mpz{?5?7>JyWpTdn7T~ z9I!hm<(ftl@Az0ody6@IgRm^jxrQ$~74JgR)z>|A;b_i?(N(N|yJ6Jt8*Lw~GG#I- z9OWBuI@y+|-(TE&@xlwLCG+SR?li=aA^)0rN-F^t+aa_hZy2{h85fr2oSaBoCdo4s zyIbg;dSbn6NJ0(-aG{}?-o@BeEmOPP50oe_W)nSaANHvTtnu5Nnf7auSqNKLUiNsl z`Qe%OZ1plesaT`O)V2=;5!l|K-wwJofRq0jV#9nqC&T{Q9w#DKrt+I_d z#Qii&}=Yn9VI-B_c_0!s?^%Du#y#)@5 z%pF(en6#@p6H`+vtm%@sD&X$KNK1=7-M-c& zy8QkWA}vlfHMA)M`0JwJ+ODW*zgrTbC+o|mCrX9<9*i~BHuHqKU%-*dL;Ywk1>}9Q zG@=2T;37AyOE`E+oU5`lPC*WZi`g1hXK;gpX}=P7x~8W4X4v?(wNQPE@KLRj8F9T0 z!`U4;<~DX#!V&N1Q>(fD4@C3`g&uGWF ze@+$03yGJbT9b|s4_yyi?V>lZUd#{D10GW1yRcTW*i8$!G$L_=@JBF%r@XILr%zy4 zpOcgEnmVn`1OVj&ybEG`mc+!{5g#B1hmOvT1c((Y;GIcH1%XuXmJDQP9)~Z5m22i3 zt80eZsi$g!PdseC7Gm7%SYJq0xad^MR}Fl|sK8)0ncKg6@ZR3m7PlF%N3+W9FykbY zXxH!LgiBj|(YRdK^sP7b4j2ahVjU#WBM~2K);JB0x6(5A{Q|<7nX$3CiAj6dGiz%$ zMI0ciBC#pH9$|;IPGx^Tw>LKCBUAes`2Ihg8pa7se0+xE7Qveh-P>0uw9*W9p_0nLAZJFg|6Rb(GNZMVI)sOF2Tm5QEhsY!dY4>{0bO+d!Ftm zB^AY0@$oz_MRo$tZ@S-gd8`v_=kmuZ&4{to>8C>6OJ76MJNxxyZaA(w7y`Hu$Z2`q zxUdKgvdqgBW*{l@@7M%_~Y*IN7{QempAoAop|KYmn##|1^t z+#m-Vn_61kH$1#?eXx1&NGReEx`h|Kv7#-Zo>Fe)1q;TbWcVjxr<>sXma8{5H7&@= z6Maw3Rv{vxrJ$@DmgCJ9${#W0=z)jcc2S$!`0x*K2yv=@y5 z*^BC%S>o-3ps~!O5h)vqiOQfr4UE^fM`w7M0Q}>gswZ7InW_?>};(NKdMx+E@~EU=eXt@gMy>qmWaDejyb%`8O1m=2`7?4tM4n{m zRwVWSt6n@_2Zdb3z5-BqD72`dp#neeJs#t)l_*LApKMMJVV-;E!0BCS%muyn-8!#q zhh&T^Ass=sLARelI@J(duSJL8IyeN_s6HOfE zhjtk9G#oR0jy)IyDQKQ(4sZ6eKaOROvCTsIHJ~B#j(xMr zW{<}l+-eum(Q9$kGBnQ_7?GbsN{2=}y;~ZHPtbrFbj2-?Ff}$dB*%2TYcpG9bqEMM z!f$>}i|svdZy8Z7!M1D`%99*Ygri3m?<;2Z7JTPByhGg<1n90 zy9HqrMt*QegOVa%zMY^MnIZ5eze1bTd=-o0i+6_WNzJUAkNvsIu`vDQ;Gox=Zp*8S z82edg4mbVMH5I{u=p{UcBswGXYN0!!0TI7yj{^-?Z~6PxpKS3;46Yy|mTzr&ByvN- zJ*6~kN&FyS7p_c>=MKh&GW-sgz|Qukmp6YY+n@a=OSAyL z74*P%2bO=2f7&{o4VXJR3~5AjZ7XbLrqSXD1xW<4D^*~V)sp4qGdz+m zL5$`sTZGoVfyatZZZmxv8te1MdkeDI`znpedu!oL86Ru>=p-9dlqz@w{OSb; z^vHQyM2y@If>c!1$)}&&h36OurrhCn>eHZ3yA}q=Mm5bYQ6Fx)zdV zkYbLRRU!GUhuS49Rf`u``8{ z3>T&k?vM@_JNwghjqtl39S}{Fs}{Pqeab*2aDFg3lcY6NtgbRMoon}VSxQb+t<34( z<3t`S^G3IYuQxU|O6=kQnvsO^0>Go9S`9l3cC3?7rJU*NAC?Wh6I$Hvt?i?1(38w1 z5hbRgf?rmV{p!c-+>icBR0GTf+BKj7tO0U*W#?=PWfL=|i$k5AlcjAC?>9aXQ9zK^ zSHm3VaoWB2Aw>a&^-~2Tc9uoX>oKdlvC~ICcl-oY~mQyB&Yq z1bl}?=Csg$a6wXGK21ZaD>$VW?4Y8gL>_{7OPE-0f)YIi-(1(hTTieNA1bt*ouTr` zSups!DXTisdW4`(ET2i~Xs|55^Ite*^hzibB-Rp*o!7WNJgzuT1r&XJjE9`q^+kCQqsz{Cjm!GrAltKlwyLa2Oi zZhjpdRaW!>#|w)K-vn710^JM=ijwKM z;%W=B0qR_AwoJ88y1~1sudk%8-k{S@%vU-Tt&GPgBf;-X`&gd`Xm-+6EL6t|en;=k0F$G+s$S%JmEAsYqXA%O(is~D{V4~OZgP5kPvwJkV zyNzNB*AT|^z2d~g?Yjxj^POE?o9D@7CF4_BwJ!9f6*!xsI5=6{z>p+o(g4L_)mWXM zwEjR#gsHdgUHejlDXPb9(#cpX8ogyF*4^=m;ZX_hhwtO5cn;8Z85kK|*L-b$m-RQ2 z^?>2kMgz#{{)-}$FNz=q?;a2Bi*Vn<(%Zcf#`kOBz7-0#BI1A=yDhvo-nj`qRAvkXJlC+;&wtMP4%ueRM&lvGxYpPy0`1tU5PJx>@9zxrog^_-) zC=7KJAmYMa1`u8!ZzSk`{+5+xGjRYAxk2@KB_f)qU-$Vq?R48fd>Zv5bvWE&LO zpRnIO>HdH`zp^qC-uDpZX!3XAUJGv2gA0_+LXG-27ED2bNxlcS-e>_0P&k{0a8p`PkVUKWGw*4ok%4-ZlLU--|6CmZYHbE%uDg3O z%zwXbZO^ac65sb1269WutHB!Yu&}dtK;IX__kNw8p+)$9kkTSmxt|D!xah5syREdD zsVUBt%Ysb+R?=1wllcn`PYSO0j99kwzZ4WSIL}6@`6%AbQ`qXoL7ssx8|K!U)ehVG zYWmN=`~qS`fo5Gm0{fe1TTc(*_FJe~kqTl=YU;#jJIWiszdTq6FYFgG`AO(@;Q209yeU(T^XF- zx#KNyoE<9X!$MD3+3E4yC&o)Q%ms^LpwZ6U)rc|`8bflS{2e5R&;C|w3b z>8&k|T0N^$ih6?iJi60%3yhZIq`1VsCV5MxZ9-$%E0sQMsVzkT(R-mK4y&ba9V^0w164+ z2gt1+mtyMdBy_2S?$<1&m#xw%Yt4j6+C6&SZNK3@E)kV;a^iG;np-m?+(#*6RAnM#vyx&qKZ^zDTiCu%i z|EGy(sC&`3VlaegeW4n^nO{{8TQ4rLnpa(x$=*y>f?^K;a#K%FFNCVKP05up7&tu< z5fLF7Kag-HhC@Ca47mz{nJm=*k<`lhLVoIcdKpxMfl=)EJg{C}t>KR++|fr-)VU06 zD%-x>KAXnRi4lcTLo+k}E9423p90TUW7?wb^Z&53vm>8`3J`ibgmtR>Len@3>566$ z3^+TagNds!+as$oHLH-_tvn54jbbbLTqUL$c8i|NcrTF)Y1=Y8sGlrPb z{2?2okFT(Nt`z}e*Y0XLXg)lOXQUaf5Fl-^GgmLh?Rujj#Z=MgQZ{c+_AOf z&4~Geq%||hc47oT(G=W@8g&7k+P{(sDE{ZQmdz`&-NJ6)QIRE(}T7RMz(iA*Z6wD_Qp+*l5)GXRZP}qfg(#T@?=1t1Bw}@-~rxFA$ zgStP6$v6KE(N1SmdsO1;khulokSyJGgpPyY7CJ@z26RKZy6}Y&3q0yC3B3*m_H#p4 zIG*M@ZJYM&+VJAvwjN+>D0?j{!7GjFuU~^-{;#;n|Ksxb|Hk0;PaYEf#{bP;`u~se z*#8mUuB9FEY##hE4IM$p3vYm&w*x!TwfcPh>Syb2Z0k~ur{FZ#VwetM6D}p+M`tNA z7!?dylPD@G-FkH(arQ;-017t_UMBR>K7m&G>r<>MM-1ftCY~2~(1Q>y6YMC=!2NIO zI8Cf`po^7{kDKkcjD_s4wd;uZ^{Zd!73~~m719DK_!f@UEKR3s2{8`uTSIYg0*7-( zaq-zZ`D{giCDz!Jxd_uX2gU^P@lC<(K8*CKk8pEmXG%tOd4)2IPGlNJVMEn$TbtT> zQEo|Yb;i!baOqifn;)ae+qd4MRq0h_psro7v+#~wBd7vu0nkPi8Y@L1vulZ0)$yBnk(P@bjJBO&ijLb6Sn=>z9u zU@U~z=9QEzW~`0?DB-~po&-A%Ha2#;0`0n&!Z;KBbV6dQ;zHm7I>?JBWZ=fs(x{76 zl9x~4_7y6f!!+ZuWQw=Yx$b!hlvw<5>)B3)dqYLam3fWtvHMvy95}tarq^VZ0iO&_ z)?eck6*PP&!>vP^jVO))qRCrpbL!dG_a*%Y?$yyElcHn{J0m5Z>fb-0)OI7dmu{d7 z+mjva?_&xg?W3U1Wo&;yXud1J{Nc86{0%tCSg8ftbz?YVz~vbr4kpKM|ED6HY#LD2FTln6h~9nLS1e)+Z}!TzxU1{-@N%4>U$`(KSAudWh|?_oRsb! z>VZ^TEWOfx)5pV|odV!Esx(MG0u4?!fiy$2Yiz7CD@*b7T;K5cYbCV;g`CnTX3-gj zb|q7@U*+5)A3XWjcQ!#rY$67+5TL1|pAwK@$ z8za-&gcERia&d4_s;f4yPw_4Nx@CB4l7Nx|(d>`~fnR8DNjTbm>W~^Y#N|C9=rusCG_* z&O;tm7*{J5)J(&`CE-)Nu$ZirblvA@AI>;cF4Q+PG^Et;f!jPJUgkM2{bx2aC+=@ykb@ujID!WV0~#6um$loEA#1Os zJc@%GoiZ8mMtsaW-DlHTY;Y{dBI z%_awjhatNPNG8vQ3{}6cUoYpOu2W=& zC<;29nwIdiv`8sdvVaBET=^#QlL3VpmknHA7W56@a#KEef3)SDwPti3aDL4J#*I(a zhI<;*aUs$>4If~xJ~0oLKo1WOd;y4&LskIpOIAXh@_*x>Dv7rY4`|PfO*VkBVa3MI z&dkA)U62FGWG-fQhc(8K?)FiX<1&uJN>~^tp_Dm2CjArpi_sL(Hc=>pvI12MBSzAW z6}FJ;m+Z{YUGCd&2`GjzF(PcX#%(RZ=u(NtA0|V!_}p@C_1ECQfSU5;2S3PB0%I0i zZ!vA@Bs~0io@zj9tz?;XJA#4xLqmtP_y{qVy>WX8pr*VLgiG)D?>FJT-ie((kfm7{ zUv4)Y2uVpKd$Jt$LdXGF{fcCU=VM1oawygWRBOb65STxMJhZV<4eR15iatiwP?HF) zIM?nAqXLsx5Jn4gTG#~Lqpsmh^L-w+Ct8nDrO%&Ji^?r&~?%KyMzdt5D>f| ziE2Jk+t#;sWpXVFpPwNezSaZ5EEt-|)m=3y&A~&^S#n=vhvO}NXnwc;aC|z86&qxi zd(yS8u4?%4*S8m+S_()9-HUods2%-Lkp>5uiOHT%3^h7NDR6Ib^3fYuZ(FYRYP(WFX0MSRJ!aGDEAa67RcXlE|Z#unfGnTS5VtnGE9oA^x<JGwpCHDbB3tY2un%v0=)2Y%47y&G@c(LD9RecI=Z2+LenS|(8raLo*qUf3t8B(qW}CGLX@tMUF*sRiCJWnKq8_YEqM+Bfv(2JIY1GC z=Sn3YxdCG&z_AF&?h0r(Nc0dl@Ui9Lo~Ws+g819`m>P!48%<3in4Y5&kJ&?i2R5bH zSo%#_wDkZ;(1sr;h<1s z<>Y)nYIDm|8pw*?9Y{5SPg&fptO&Gigj(Sc81_sRM z53S@v(%q%w5*hACRZsY0o&92GXDux*H#ReiZ8LPKVQ-P?GR@1&hvgyS2P(^O5AK_g zN+pzq`v!QKXVtziLs*Y9cw;nf&tx0_&`0-kVPWg4x~|FQk6^Zozi@Ew~3M z$(WFQkvu%yZhE-+H}1Rzd}|r%r|-i*0U8f+VctzU88NX;I~Td4hM*w$qx;_^r%w|< zlL)=IH90Ynw0sft_#W}C?d`;BywbLI&A&kJj7_>m$l!*ED=WJeVcK4m6v=5S8e!dJqQuwcFm1{F5oW&#)gC*lhxghS_^HSnv;Gh<(QW#R~ zrcH{CUjn;mK7$#?C1OZ&+M+mDTb-2Gn@!5C8%dsa_*J4JjxoYf%>XNu?;mWjgpW}n zd!pf2k@?7nZgUyQ`$!Nq^{bIAcK^@|UZ^tVKLH_$R;w~I5LIs#0;x|~%axQR(81rK zxIDwW{iudys^>F-7d_>BwKWih)a(<3V!NTLEc%BtzGWXajG6VNq;kz0=QlQR@W_Vy z`&mQ~&;cpl-+?YGt)VEjxfbyX6rF)3Tr#rlwWYtU2nU8hxrltc*muNyMiXy=Db28V zk42nI?gg*i)=N!IS2?*x;Bt->s2A&<&zx0@vh;ShsKiJP&(4zJ;c>ieoZp!b1VcpO zb>^#8BzpW%%ZQF9p&hq1A-((Qz46{1i8oqc3b zuP^%Y#X+)k@wx_M;42txFe3_1PO_4clFXpjof;Q*z4Fph)A4GonCf$PZi};*=AMLTTauT{Qyy*^3?FU>DyGhPBkzZ`T{u~?{4K`z00%cuDEyC&OzAsBzg|Zd& zxWVvab#c)Mnule2A%X&qwkU(vU(>GQd2E8#KPk5o06#K+879{|I{Krpuc#vPc&T&9 z^Fmi*@XTm=mtHkt;93#L2KrRyh3aIpW&@G4w>Ce;cc5Oxt?)LUkA~8@m?~e41 z^_9Z8$x3|Ti+^aGImptAIbB^{kSz&}_@PV>{cQ#LxyMIGEv9%q+A*D`8NL2M8eUsl zyMWBKV}*-%zEIiMM9KSo9_t*&Y+su1EYRp`9=Yb?E9ZnWBSsrz$} z?dzgJ+uWzt5uoMtCfCp#5gMCKl_DoJ=Xzjx03^PwytEEVg!7JI;M|TX(YXgPYDVp9 zx9tsSK9|ky*j=Mts6E@-dIw&tn9ic)C&CQRw)pAGJ>LN}WSClhLM55k{!~frabzrb zTWbkbthF25dbXggi((+2FgD;(Dml6K^V6Ktv=+$sDF0$&iV(MYH+A@3=OpmbswBEY`$Zign1`Cu{}MZ3CZeo zEA1&b_-lSbNOyq6pPWtb$=4V0oxw6ZM!-^G)a2A2Xu<5jvgCsxu9D{K#nn|xM!V3{ z;`hY%T!XAu!2rhMqkO`;d6XC#$qIF005dXPA+X#0K#$bE6@K|BE-qd&9{V0ve4a`b zzTcmprKnr@y8dOGAN3-^5W*@A zl+et~tYzKke}#6J(6A&)mMJLc5%u-0uvk@$R%TG)rlw*qDubLB7aJEg9?5l_ZGiF` z>DJ`pQfsNL%CXzj{QrVy@3t^ES5g{bo>KZuOycC^gk+*!FO(rC}Ws1NHqd@tbSJ%7CuLKg?`hKUX@g*`Ory})vXu;@Zd?th@yheo+f z|CkrZS z`s|iy{rOdHsLV#>pI`#4W;2q#Kp?MIxrD2tc{X&~ z)n!}^bwUN`=tuawy9)L%0{#tOx7vFTsD(6A1DVA3?_kOVhc`1TSf?Nb?I3J;mOm-Z z5}v@#J@&>WZKZ3OV10Zr(@*bNS)CgdRU1W%pc++=Z?i#W$kek!+}_8V1V~T zPo68+84X9m)ln_o$7kG9J>vLa%qYHc^ILIQTiuS6TyL$VJo1xNEK5Lq>vbP)uA_1r zN>g$u6d{wBBeLqns=;N#We0yiBkguffq)3yjr!Ui#BA&^B1k=cFnpzI!<2 z?|=8Q^Nt0e88WBE@uoH3Akja-*_s_1GBq@`JRLZ6{B1y9e-CxP-4C@XHZ6^t&)zIK zL);qE^5o1h=)>1KSn!B4^fTZ-1KdtsPREK`FgO|yeQ&u7wSJKXt)cH%hDwy39ru_( ze9y!~Ku@L3OR2{aL5X&x`Wd4erT;UJrjY&#y+~mHKq@1LbOJ7;5n_lfTtS}<83 zTju6xW2Zk(?Ytotn7uNE#y}^{I+p7gyO1@0v~7+v4S-gIUI{QIpDk5r6D4FdP=Mmh z(tr=^cwfQp_rqB-rI}3{oO>@6-t&3hXd!+bGYt2efvk`sTdQI!Gxy2JjFc8IhW^bB z-zjfE4;YcW@~3^3s%+PIP(}5@M^3jFrE@ zW-vF{|G9Rguy*!Wwq$m)fZU!#`yKpAdPGHp@ahJa{iAm|mMV@Z*PT zTku`fFBzp8)+Do8YvNPCW^A837hHkO2Y%s=~bzvl(hp;i7RkXwx|l0?}3nt<|L|y@{C~@b!7mLV(Gz z(02~wCcJ$7rY0}3hON8m;Mjr1ZX}VwV@k$_lryW<4u^E4F-R70IIrQ|CoPyi6>bDgc9}+>b#NE?G5oy7RANCq zC^dV>kKa$r?eMg0QwdnIu%JKX;Q{dm_UA;|I;bBrwy^Nq(1?yM{k^(^>+R>~;86YM z8ZyDc%6>h;$dpO?eRLEYk~lvzUV#AC%5>irKk5VNlw?)rjFre*rSOqLvXr=)H1K4i9zK^Y% znl{S7tZxQa*(R#~T=Q3Y5a6{2k2r%mR}!y1U_YF}qYh3{ZY>@%zGjo#B-C^PX^Z<%1)Nl#ZSr*EK>yqTy3Lo2_7=_I7kILoxeZoJfOS;V%K1 z(8i7PfM4_SZGw7ma0qZ1`$tFZ0Rva%L$HqnW*PRM9bH|5jUFLd4R%rkHuRCvc>;IP z$WZ=p%Z2N8vP@%_vDH2D+vnU*9mktVLC?PoZW=B2O()r$kZz^taJCJjxA+-vQ~-b^~Nvi6p7`SSF% z^D*%NXCJrSl8uavfPPqL94R5LH^s>Mt5r-p)R|m^@TAsWUfMgi3_;=P+V*Q`xzQ?qUtCr;3>0k4;rTh9qCZ6*Dc=Fxs9dP( z+p_zgC~VSPP0%E<(n9jfdPID7dYN9_9{$3CT4C!Q_9@<#*PvxP_nrQXk*R4CCxhwW z3I}9!CP=MeJa7eWLzCTHGuE$OI*DT>Kx!iC_m99(Ppi}6DQ<1X_#Xtzj9CwFH$Vao-ZN zzeH!}LKO_EskFHK>3^jFL$KjX9PnRw!2iH!;rspH1^oVhBu_>8X2#aU#@;~!FXa=u zoJXk!z`pz^$@(N9Nv*egR{2p z87VW)hWkI}N0Is=Ad;Mh(bg74V@(y$if_p`jc*zJXpWhy>>7fZ^jemC4(#-@aM{iv z0#PRB!7zR{NePT*FUwbeMP63^&D7X9A_E<6$-BFA-QB#961y)g;DpMJgM1Yb;GblL zun>Gr>%4g0MqWaqqIZ3h-*RXgZiQXtBYRaF#LR5GP|bEd&cTZ&d4~Cb-)v+nF4b2f zU4es>eS5}LP8bOc5=%=)^g#srn=w4Lm=W^4CTWtd=IB@@Cg@q%pnl?*_8)C2uZ+R3ntO>R#vKlf>yG! zg;6DoxrKEPGYG}Q0u-|8p{EyZFR-d=9BRD59r4U28)}lEVrg)&B+YNU$ZB}PmhL)l z2(MIwZfwKvEOVvNSTZjJcOk@yIc*&*v{cGGW%0+&Lg;dO1P$)Dwh+?1bEoEJW-f%! zvwYXnO}r%_O7$cKklVN+{aog(dP{)e%Xa9Jaf;C6dp=J8_ zzblC~jCbyNDNt$XjAW!De2r^TP@;q>(djw9ql@L|=eHQqPO!i=aBFdMe0H{w1RINh z2U0Z(7(OqofH(;=a2C?#c{ut5G>1|SiaiDf1`4%gqIMqPoI3gd&E^x_EQ-M;1mgla zWd=KIYZg}4Ca0oFxM%rIrNdkfn4&P0Gr$wGQjkzQD1{r7%7Y_h!S0CWOyHBT2>dNU ztwls3p0?_q{7Z@ofgdU(y90Pvr}H0LdiuRoEv*B|3eU>$OH`F zXitgG{O5uK#wB#p0R0eVl~6+g7xtLwXmY{l^_V!sA0$M5bubBW-@bdN zsyr&Ert}6VTMJSN;T=%$4Qb1Vi_lBvO{H5|*TgulHC`CazSjlgBqb#!m}gB-zgOmp z&1W)a=YWbJXst69KOm*>WyuUE##(71gs7du$|LBj1`#M|SoelekTBtf=yNT5qMHFW zLVx}1;7Ht~XZD@^ejv;1BxOa#fSXW(kn(}2UO)`y0U-JK4$XyBXbHQ>X(>6L?jHh8 zc-oPb?HjZLMY2n@m#)u4$tf)S_51(g?X9D# zY}b8ZED#k?3{p@+8kBBSTDlvgySr6Xl+KB?bc1x4NO#Ail#=eQ??TsF`>g$)y~o*O zoN?w~yvjR;`8>~kU-vJiN-sQ^aV!*=xDWP-<%e!Ha3E;-JHKQnooK8o|$|l- z#MK{o>fZ=N?Y#(@kM)w)?Y7uO3MCVm)x5aaRRnf+oU<=^r;7|5JV;956-)WG)=CQz zt3>;Y)Ugj^ONMxU}K7;&X z8wYF1ZT>DophmDN%fez$GJ(P%;rLjYjD%6%4@hg+BZ2NXbzid8hBgr`$eu)nf;)(N zA(Plj)P(q>;9wbj{bCWeY2dT25{l@3bmPR^=OoO@%wAkyFD)tvGNP=&^Tutk`^!!J z&e(Cff+=z6IeyADxoSILdg2~1|G%Mg#!kV2JM{4OLg1t5ks@b*XmtCMERVS|AlIAK zgW0}fmf~vu%nmw~28ITFwFL-5Dkg;aLV~lAs-S_}18|E;8 zy;rR~Yh_ocF+`)SMgCOQ!*Uj<8OSnyo9AP|G5!Oc3~P1yM!-_Kr_xeDdQq0(O~ z)y|Hm+ep4?^y?4SN!8T7P*Ya`n`*Y@Mfk@yoqIf82$`M zZsiiUpFk?!^1p?)BIM3L)6&k#$vJ)I&BHf8f6varPO@L!!hwBo(7p`JVVQZR_evp9 z9124P*%C>io=lcn;gd%PbG6S)K;u^&AYzgk@Dj7mXIBLX{`EWS1QuWOW^WdVp?w+Xckq3OhFAds zB5$9E5=-Autv`DTT!w3b`}e|qma>%kiiY{|+~wa!78|De%t@4G@++0WJ0I}eCx zn;toiRByleeJsZ^K%zrdfX*Q0NMYCv&I7W}IRi)m`ymkiiskiaZddN=)anFKc6oUb zzXOU=QtYQD8}^4YWHCy;GYsjYq9d<)Ulorg3h;&`*g)?9UtZyL3!|QDhm^i*UUnGx zHA~#Im6e}r(qHIr{ycRnPcLLlM0r1w*?T|fW>eE-1zY%42Flj|i&=P|tqn3txqtEl zlf505dSl&ej2Cz<^N|0C{7-tsA|%q|)KHitQ! zxaZ%6amrrm(e!PgHiW0}yvqt!t|nn53ctUQ2`yq>BrPObyJUm-`lV`p-MfE$q&vUR z)dfHN<3B`dpms+lE_OM$sr(z=@GWRS1LBPT)XEaOm~XW{`VYPV{!J07Kc{A}jDvw2 zR;BylgGUlsxQSHC=eTY?1)*cA~wj8B62CL88x7Iq+!4Lv=#nba#? z?y{{a0&9Pl=*~M)$gtz8IlsgNX|Xs0SAavOatQTm8-Otca1()~Dk=Jw={V z!MR=Zw=T?W5Hk&WFbQ#S4@mOAiPHs-P**oim1{CH^Xf>A6d_e>;jbj!R00A5n()km zf~_mZ0Xnl=_iwtpSDP*`Raf&oLxRalpD}uoi39@!0~V25WC@!0>UA~m7Gv!)9IlKH z*~ys&^KFAgVPRx^eCvtd`yTV%e)_j$)eqv5OX7m#+|S1K{fdeT#>{=?bpzw(_c2w~F%VfH=(Qf*;jxF-;-ll^M-OkKwG_6 z5!#HcnCRpZen)dLI19<^4XtvKlk3An-X6g)(807abP0_%G3ar>5R;tT`2Nlg=KkC1 zU%$e*O;gqBn>QzihKTNRO>|G8%?w*ALykxUj5ZV>CPuzl-xp#XV1w~*da%w42*P>Z z=Y7eK%N{4ydsvKCTv`;;ej#IQ3`X^SF$Qx+X4&%!+zk$|^n2Q%F5()pG_d%Xb|JvJ zvv?nh9wfBca?`l}aLSJtgP2#5;8oI6QK37!XSHu-Z}n}s%P)i=Q?nRLhWTiv&^(dn zq`WY~r%KGyaJ=41)Oz%$8tVbt0kD^!I2`}L*}$y$m6eynz5VdNuOkHt_7FfRXd`V_ z0uep%Q%ku5`y$qZgj8_sfQWu@J^p%rJe^bupk8C|jVbra%B(Dc1k}X$pn73SV|YCa z{tzE8{43CL2Z#M1G)vQ@6k3(W|3borPdbeLK;b;&Xz#ouxYmNpAMMsPzjSiCK3|Xf zPv~1IL;mnk@WzLu>{2*e9WY-Hybg((1XQRtcY{5Ipc##ql*jdG$7&_5gzMzy^gpqH z;XrUizGoNly>atZG8&)ZxAW`zCGLec8zLB{oPaPQcdyIRHr9XE774NK_TA`kS0|?3 zf;A=$?bV%ha-mCCSc(t`L^_!ehcH)hcJ@oh`MnZ|-#<&Yg#m1GXBJrgSLlxD))E%%DydcpC|cPVi=37rl@SA3T9H&!5-+9oC-S7J$t6ZoEIO zoTRg9|0Sd?n8gO4o(nZB^DZu52QC0$=@BCn6Do#0J4f3)#vh)(teyj$wXD1{aq9tj z(XU?xz;D_kD)^#hTcf0+GB?iH24gA{$ondw&9Vl{B9Nt(GIoyE)^R)(&**uVpu*bR zEb+`|1<~GkqVqK=iNEqY+OVgmvTO3m`N}Dp9l>zTy7L2+cjz4)Xu{*m~%F`?mQ@imTN$C@(k5JVuJeu-_Z^r-|HtbkUq?Z}TdV(I9Dshn!s0 zAp!L^^(csa4CipkdegH^rEdx!c|EdjnmRvfg?5BQT@ng|>BDTd^dJ;@v1fX z4px(5iP`&fI0!5``$n_`pGK^>RRpsTW`|F;2de!S95wVQ5 zR=qJrJG1P|L4-elCO|v|0ICr-D#PtaX#lJDVj&W&{n~l$`5|dB4*x5YzLDXF`s;Us ze}Zmh&mWAW;LheXx=DKaVq<6LlTW}%;qljw_Ku2OnzVVn^$AmsBz`Pp@lcR8E!%Mx-xSqXum`eB#7J5rCxx|@^QEwgapPAn zIA*X$ikp<)dz=Ll&}hP7>y|qu%%xN)C@2>nLUMk-XsXI6-l4N&U%#B&sauoN>1*b_ zdUL_$p`8+N2~V8}7I?|%Gn(X@Wx1pQ#I zGT{QIBxmH8muEQ3Iy9v!4Z&s!=LlB_hae(aBlh@KUYKO-$F*v-zOlP2DJ6xF*KhJ8 zY`q!wtkU{)=$k9s-md6N>urOxE2U5Sh~FZ4(ptJpwnAvo z%H_9<_C%EOWKpLQbR0A64|+CX&dhPvF7E&hiuXs^!*q*8|%i2!Rh zPMy`F6FtZ7n5SHB)HS}igdDHXPji_G{4g;U31+c>;OUM`Pq%ymF`Gm~<+e8bK!`7lGZQsNMlM7RI)+DlhqbI&;yWVXo#`(vX zYr8?EPGO!@*=3ZvZJ#$+oaCj{>Ml*=u^LYLt>v!S8ZuBh8NiiA*$BGM{zh1^?h=X> z;blw|6rvEtOYkV5pjg>lCH(V6-QvafUA)qS;oB}=F+`Wp{(NEO@<02ga!N^~Q{SwC z$TpuP*ykz#yvg+8yc-X@O`1f2-z}vDTbn}Cr0@6t{LO}&?U0&$S4_>)HjnI)RM;>1Cc&H)GUim?4xpw`l?z}w+RWE zonH;X>g-+8Ys73&sB$QH5_0_g?!wQX87K$k%s$`aTMb8Sx7SS-r_!9u@Q*nPo!=`Q zbYFuHea#q)eP9v~S+Z87|3H=`*qd&b-E}@Or~RX93U|~%7+K`nk@k7CrR6IL3H*Cj zdIl0-!gzX-NU?cfA3RU2J$3m*Rqx-ygQ9V9PfyPr#s2<&+ntt-ld8+ew@~ZJpR=^` zd%SYr3glU;_i^uigA@z~2Cu7lJUrFM`w!{qsY7k5v(7#gxAXIR6|0(idY;d<4@{k6W%e)6jLu_%-N#?56%6|WZKn!&S(4%vKXqus3K>NjKGi~U{ zl^v9xN;hJD@#0e7R-sglg@r}9G=Iq>g@XFCvr8(bgG(vI?%&FjlD6k0OhI|5XWB-RckGmfh%X=tww&v2F{&!5*>86H1H%tslT|$|5p3}P|{Q9e>PG8yg z?>cIE7|0F6K=z%F)D#qIsjzzMMMY>mb+$n#sosTSKyPq3RmDj0}q(dq>U}`Dzf(a20-#PfYN@8UZidfY57% z<^8Fkthk1XdUDXf+vu|FZT?=y8#m%MML!tt+IGH|w_{uRiG5PY0^;9}Q$t_he!Cj; zVRK+CB7$>$VcnD&f6$I!UTN?Q8Gn}Bb$qP$k=EYPQA$h-f!F`0Rn_S5tzd}(Yczku zOE~&k?Jjk`;}YDG9X7FC58|mQv+jf|@9X=j)O;f2@5R5vu2R?A(?fYl*j^&1LRm$o z+T6Dx_k@(BVPNuZUhQE>j&$Czu%IxIw1Uk7Z92Ac?LGHdRQ-K@eODzBFBGtSTROfA z+OD)~>>#8(zIsjrPR(R6|HNM^NC|E;|1YA6*hLeMMBUN{M)SCL(%0v&tVxsg`9 z%-?5~AASZI6&3TTh`T_MZ&uTOCi`Fd3X(oJ#gQJQW(Z^+UF*hiEGl)A=thk z5aUBbyslk4P|_-flRGrX0ugpIIi+kF8X|wLR-LrukQcv={|oW}7oS&s2UmArP?Xs5 z=LbZ{sLA0xAc~4&J)8GGfh`)M+-rBcQelax){GB{BFh(ak0mc*cUak3Vi5y&^&)9S zTUf{-irL6?{hMMegdHq4MQE1UR*Ho9?(FD&=5wiV-LjYnW)1mL_06HtpTOCrTFhq` zz4-9(8gNsao6lyN8bR~`s_0Cq+?;H?*=?OaKcf@k_qaMnn_Ne8v)cC$;EE|NwHHBX zpW|2OZ!yuSvm@J)%R7rVOr%^%QiHyM#6(h9(!e*qn|lP>cOF;FsLuJ+ z)CXP>kGZ+YpkIuPOypO{_5%G>SsaC$h2=V^wSuc#hVxywYOOyn<>s61?znA22Jsix@C42kgl0j&OaoHtd@*5Be zYH4I78;{WG?(c6vHUkt))vEr*2S-13eX=SmO+c;^I!5JR0x# zHSu0U*-&SiVlyPl-*RCC0yV!LJ zz296xdE-5MRoCja^4~|d*ZA+=h(hr{+l}MyazA-cNBKlw3L+VcJ);UF)7oQM%fEd~ zE=i@oU=XP4YpPYA#q&Dz(sGmW^0M;PLPBAyVmKmhWqDacR+e6Y-%(ywRTIkmDz`T_ zq)X+L)U;Gpdo5Q=ABwuV8rH`qh7FLNqtwE1F`5Zaj--Wyq0;bfR_RJ<y)Y;Kz7rL-7 z%oabNxah9_6AMV>DDa7njt;|`2(F)|y5wEKb-cxo7N}8+NFxG8NtXI^lj1QdxdIZB z?zE_qz2I|0l$B@z=$$8 zNqp%z6C8AtT@3PZ7F$XrPbuH@-$g-TzkLa9gSMqbyw+x}No3eKns3TvN{+v%xFnw4 z+5yh{3Rw{=2NtDzBw`Vr5y{h)mYyriOhmkPFY_JplxuW?>1w}$m}2Z?R521A^)Y$HFYI-_lJ> zg9(23AfJg7M+2$~$DNrX=+!nF=gnnnoLa}ubCb-<+QKqK7f`AdIT#_VNyX!K3N6qBXI5YCkN_3H@Lku_Z3i(hnlCn{PE zvM9BbD^G}t-8uG(={3rz%lXaBcFNw5#EiG9<~S_uyOK@d9zOt4e^*>Nv*Fs#!GZEI zaZ_W!YNhAy@-VpzB^9I;*g#X(SjjHhoMA{OD+`OGgB|R8uMpbt3F*nROX1OQAgXq+ z8o+jRbmX8eX7d&=bt@#L=KS8+*mz(&i4(_p#@-$$Y&~Y!za1ctEq9AV8E4OaB8A|!ul$=#$uw%{cy{^d>lHeo)-C^jK_xa z$k4}|m@Ey1jEx=jd<)X2dC)eONDJ6%8_WGgR3f9HmGOfETv4+igLM9@I1Y|r4nKMkazJFf^DHxEL3vSWM3iRRGupiNETWYG19eX8$Ha1OJ z_j>D{ib_|wzmzo;?&9Eta+w!|iMftCy?$Lse&~UJOitbbPo(v!B4`vNBD6;ft_`u0 zu4#xoAeH$Pm2m6V{1SElnV&#F~nNOM~D;tt35lFVrXE z;?-7XJ~a76n5v9wh{>vcRVfA zlJrqy+rHv;ncOkxhcta}?V*dXgniBcAed|{=2btgE>*wY-Nn#y-^@7`s)3e2IJ0-0 zoW)Otf0fAJ`9^8u=ve8rndvgqN_=*pX(yg+-ZRd?J2f^qNSE+Y0KIhk=Ac@G$95&# z6)#$)Gdw(F(p8OL_r*4X9h*x`V}}@T2X-|IzQf{hoK4QkPDfnbfCxU&_bgq4fN9jL z2kqhl@@3-Ww!wTj*uRrg10q;up&O4pqxq*-bEm;}ESI2-iP+C#)6!qfjev(~mAh%k z-fESAgMBij%c-QoR2#$oOd+73bxBy#qU6Lqs7RzbM_h6ei*G!;#+}0hU7yvnL~vdz zzGh=GPg9BT1uuq_S2HewqrC%i>h4tl^qyT{SgL+#( zsOagHscQ)e3%BVQ8b+Laq~)V(9}FG?<+Y>-4Z;gO@OmhMp|)VH-&0vO8VXQ>V57%* ztulId4sGuiBwd`XEgM2W1-HqqDv7qY;7Sh6@jPpu&9 zG2=4X5m|l{r!z8&3Hm!ueta%8VW2qVhc>PgDNm=gk`l1}&|n8sB9aT#hhB;MSelq1 zm?TMh%eM_g+(LtJ8Ge3v&(NPLf!Mbo=$G#!L}!PF+`&JZZV5K^33Yo;4bjaB3mu*b z9-9*UCPHz)m+P7Fyriyv{tyO$97e)%{Egu~*th*C8M0_;vVe*Ma}KdQIbR=UG(*b= zpJY^7h;`-FHRy^(3fi;D;*!Im$A}*qkeTtlG>rwo|M0Y%Wrn}^(py0o1Xf^5q2MMo;gl)}}-hlxUy18P= zkv?Re^rZQ2VHv%1{7of=epd+n4#hkl9Qee9g`_lyob$7y2^vJe65&YP`l!5 zW1_j7*G}+C#_NT?U-$H!f}_t=xd!FoyQ`GjI9zInT3q*j@cq^gTejJ-&}#zs$dC00pEiCB5|@|^jBinfZ0YJr>g`Dr(C zMm4UiY-m%>8l`LCr(2d5HF-3OVq(iMBcqvXzq5bTcLAKOl5NeaF=Wlf#SzK$-hmT) zm~&+CT~8Cqy-6N#9Uao>fwX)hmb}{hXY}+!?k!>-n)NFj{cw{n=k$uo$=SZtsgg{S zs|=D?RA}d*_mmn?8w|-Ng=QwjTb#I}FD0IYj?oFWEb-P%J`vU>-+Y$5{q02W~FVB9TMw%nMqXB@JsL^2eaC>($M(ga&$Z9C1 z1)dHOF)?1}6EhGT=BOw7$HbVG#|0C=*Wdj8GZY=&+9t<-TWIpD=Bdx_nX`QvhJw30 z6phE$*2bUQpu=%0**ZCSH!!eyCs=#wb;{2>+69OcJBS2-%qQ2545n*Oy|=u|WU*$k z#Z{ty)j%&k?Sz;d!BqW|%K3Hj5q39+z1Yb1+QTi3`=+mUXw zButJB>deCp4W|uQtd3)`5=qPd4*BoWa0;>IPT@POH`VZpQd&%QcuqgSC!jkmDJWpt z+FnaeOFK9^On>`*CsJ;%D7;j~DvgrKG;ywzwe+{T9juJ&>+5^~aa4Lo&r%8L){e2v zH2HI*v+JcnhO%Pz72g)(8;vfCs)0-lTwJ!N9~D4OKfG8ZOHM#VOG)Iy4ck|5Z!n-? zl(e+5QK2b=CK6AYngOW^5U9JveZ^ym*yB_+PCY+831v*YL!?lvDprf#y-A*pt#qcj zyGX^8@Bw1VQkS;jZrhxeT6BtZbqSsUH*aOg-RADDXg=HeL=L{SalOq8lf#P4nJ#6E&Gc-= zE4+=IRlh5CvkbZ;bCqjF7P_?*yWg!luBhhQYyyUro%IEinDg1o3T+~X!;OR)pc=9a z0)XMd#=B+ixi3Ia@Bw_a+WWb2U2J&^{uQ3Sf4LBm5=sUYjRFFxWjgBSfEeif4fo^M z^kH!f+G%Ef9pYryHI4@$qI|Yv)CejOVphJ3@iVuDirjrsX0k>jV+#fEb@M{Pg*DJV zbVhP%xJRp%uAD5s?RN<7g3YRWYw0L?6MZWrFfl)0#eM7!>=H@;f4%|lwCmDN?onOc zo1>$TZ_h4WD+72tt9}}iG#HE8+S{j>GKp2m%im;0XK|MN=HJ-fA2eZZShJ=@U3G_h z;Bi9z`uSnfv)r|xKiB?}7OWEy?^;+--Q4l9>`Mb1CnCA}r)@ zFS7A({DJdU(f)Lh5h(?m>&j}%=1BkTKmW^ynbkWY!e8Jg0O2*3*^}O;BaEzj!dCXS zyNphtYxoEIkg-5`shL42sh1X}M^^f=h6W9~jEoHA>CD@`J=!Ej-G5>Mm~*`X0w3}G zn?M~scjvbqC%Uz2lp2_}{{k{rfworx=zT&{`)PR63GABPW~^+itfeI-f`T8R&PU{@ zx953PUUxe8I}q-|`N(6Vv^z}rHtz59?_+b2cv|T(lK1y_bp<>qsUWceNI6EE4lh4N z#lSfOgtorERG3|Z9;5rtPaNQrOn#;+4PQe;17D=;ey-P^KMTJ9>?2Zhlbx~V{D*(u zDb7%`$BX~+O?37W^9c?Yn*_|d&7Q@NuzVsGyVmzd`Y<+EhlpX)E!COPF(U_`(Zh(_ z%W&QqMk;B_6fb+9nxN*NH7aOpKla9o{ql^dxuIdgh&hhKcC+t87VH-c*%}FhCNQ<0 zZ8U4$fAC=aZ1YW#R+XOSNg3{FS6$t6?H8>Ow5ewhw%QTPMoP-0fe$f>?GBhLd?Aj@ z0smlO&eGCPLfqV;d+k_EjC$p!tLyRE))^n~nN?v$ncG|t~D+yNJiRA9%%L}z1TO1blw=G2|ty$q(eZ$XN` z2@8Vf@p76$Xv%Pt+Pc||n^^EksmUv6mXtf}&VzVOPYBxw{jOXy1qBhO)ynazD|{mR zpt96&Dv14xA}XY+Hg+*P6r>LtPaO}MVrz?h?;9KAZF5jnQ`Pd&f2a$O1iYSplG~eZ zY3(ejzJ~^hBjJEV*HM}`k^gAj86OohsdyYf#6i^$D27@zAe>oDI1HLF8N4}vio`QC zp6VG1L&VYMg@q+cE=xR<=?&&H<@)os&*y+*TN|eei7=PR8>R{985*)+jC6B%7c##4 zfQSV8gk01_?Gq^QUzv2RbFumS)I@8q=S7j z``g0&)Npo<)V3ANo~^<5^{l6~9Iyf`xLp#Ko0-9PO{~so818QFo+?c#A5?_j+w*jp z&E@!r_iV#=J{3_`_T>#qEdch#ivDCU(1yh)m1nTfOO{)mwZ(FM*qbxoUjw4&;>G8? zeT^`%J4dZFO(MQvG2H%wHQJvnBLMS)gS~A|W(gU-pkPX90n@BK>{6;(nAc@hWqA>+ zrp1nx+V^nU9i9jYeu(F`R-|i<;9%_b zu2qlMV`b+zfpNMeW289j!`t)SRSv6)z&-qZLY%}`9>MnMxNYE}rDX|e24&XyAs1cL z?q`b#IEEM3<3yK2I@jUxv4Md^kX=%7%IbD^$rn`dw(D%ykv9S#@=PF+5g{SWwu%Az zT=AA!d6u`XZ^Sd&ha?k(B&?ixlvYH@l<2ZXGia8PFx_S9E1)p^yFS+a1;s6bWqvNR zWoKq*dswx%Y(Q-a=WIs4g+(r^m!X_o`?q5JoF`;tWe`E`&)U@0-ri%VeF0rw1LeMh z{aF>kT_6`hF6^;3x%tJ($z_k=_`dK{{NoF5Z#CFLW^)%^2?fPTb8+^irgH^ko)|IX z6BDnam71-O)b4-!bsbu(fKnq>j1KP#klgMjzL@*o9?N|O(lMzw{X`tt34^9ro+iI{ zT|!%*X@|Ble+6>;+xP_0$&?rh3U^kF?k!AjyS9tl39c%2)AXM&{`)QG|7c(O@4iX> z9*SgFLjw;73l%eSSw{Zh-YTRzu@<|@?g?OFVcFNfy_B9_lvgUHAujHNg^sSc02-K^ zH+@{!6*5dUYCW=YiYGi6mZvC@LX57WeNfv{@Ne#3P)U^n?0(tn^2L1c<_eG{UFMr1t~S8_67K0e5>oBtvi;UN6!r)gN(dNM1nv| zULGvanL|xKgp7;u?MX?R zG3%gBy>fVHAOr91{{knE7#3NAxfQH2kwLf9Y)S{4{s4TYbB(3T!=pN-tw;Qk#BG~%ZpULvu~a-+m)Ax?yqq$7fHBl%)sGtj**sx zI_Aw4sThGPG)fGg{r&q)iruT-(J%?=%H(M0u<>)1i$}Vh`*#W47aS6`R1jxW);*-BWWPJn%1cVttjT?xemuOcpxrWRdV6|k1}8%+848xyLT*WMiVTY+Xk}X{%^&jbFFomo8Qz;OX=yK zE{Bkb(O5Tp&@D_^9KYymEuC@~WIYZHtO-K}*%JUei#tHycWH(+?tAR2YQ=B%OVuEP z>;{*}Yiev_3_h#Y96Ll*;HZ>lWkLBs0}{DBlHVV}pcyLX0i==}e!<+?TaRlfD0KKn)4&ce^5O*iAAOvvkX_tWPf%KYsGN5pfd^A(QZR8z_2G-J2>+S=dUyh^JLG=LBYZ%I_;u_M3|oSg%h?$ZB57WmGyR(U zp!W>>LpomDBa2)_e|c%C)Y%gdPl?F-iQ(k6y%oKcKmS2r_C7W?vwPD3{Kia%^w85T z)fR_~LrgknI-IisK)E%k)?^rA6X^EtFUQ~GP@C(Q&TjavoHldM6rY5l)o7NTt-3(6 z&;R?o#J)ZsSO|tSkzWT@&X!;H#rO2Qj#YF$b`zUTBW*g@Y>wQ#en_QE-*<0X^d=^H$YL(>zSwoAWdo1b(qCsWL(}xy$dA~x*3&a` z!^a>XA~n@N;>+`gg-JCvKeHHWili!7GR3Vpb!u1W>WlhK0mA`+hup# zC>u3H$c-3DaOY`Ml6&5e?GJ%4ReGwAvrn)cUpc$D6o}_(mUCF^WD=&C4+Mf#0^OPn zv@n#xf}daWo>&zg?adv`xlNsnK8WOVKl%<2q=xm?LuPIaB3-lb!BKNhDL8~VHC=2X zIY1>X=asaR3oGsk9Ev*Y2t}RX9&dVUr5D?jlPEo6gib;}3-y?jm&d(m(Um#X&Bdyn zd7j6q=3IbX6nOq>%?MqX%``abh?(Fc!i|ps)|RD-Ky-jPxhD4oW>QA0O+K6Myu4c7 zE7tQ%+>$?7$BP*8IMlN&$w4N-I$aHv1X$lPJnDA0==YwDk- z>i_iVDGNh-PDbg}JGW90+Q98hz)j~*jtQkk(6*HkA0J;o{rFP+*!`FJr~x4sln6{Y zL{4$Z!kafrzXlH8xA+9(}#{svW{k_t>$L)?1HJNoi2z*KKTUGNhfY zZ8$Ymtu>G3e8)IQ97WD3W#&KMH5}yC!Zt}xAwTaYp3KO}sdf74bAVY(KmeY`YiKXW4GT>FED?zm(tdYjCc2C{t@3EGq5iaa7Es^BA3vN9GfFDj zwzBfB-Ytpu1)@+fTRn#N@!UyyyGbih(f5`ysPy&2y*{#ri50{Ab%@7G!YEGPI%{HR zhL%W{Mn;X0CT&*4CM47&;FO_%Z`N$PGO{>zve(%f%7o6oaWiN=E^BuZgTSl)Q9ti; zakU#dn`eyz{RIEZcOa*U@^gJAB1!S8N2xV_c!y6v(JCQ8CtB{ro6Yd+BUx3 z#*z~I`fplla%_qCpo+snOEN=_Z|g?JqJolZ$=|*O0WA&*=NY6QTk6|YVq#*99)6o? z0+druE|g3@CnKYfFwNKZv>Vw32gchdq5?1Eg%c)Ol7^SjY9B6BHUg;J#KRIz$b_0% z6}!EV8&I6zn|=Z7;{Z$j1LTO{XtQ2hNhvg>&m@ObU~H>f6+v>lJ3G|-9%zc$eA}8e zcJ5*RTIDwUHa-_y-k|RZb(Y@?Bjs-=LXfJFB}Ad~{ry1Ej^6R+D|6H%wAq4|&IyT2 zM119MurM)q_V!FHYon!;VbL*`2`1ONd25Fam%GG#G((x#hE{9rel{X&?DvtIrF=0tWAxL=~&LK-83LXS2a_&t7f@K4UrV_8(y?C z!3k;0G!d2Of9bVkLRTz0bcfR{w#2NWqGHZ6;J*Ngrw3-SMe-+i=%2kkv7w3J0WQv_ zQ(D!=@wqgRqCj8|yk$*HBE8>UhFjWPW?ilcbZO>^q?&>P(@IY=V7mzaDci-q;uu0P z;Z5*NrQ^u^=*PShD)$RZlD&di4wYD&+x!0h{zE1#jg7Y$eYC#+8_c`@`?okgA3ZyJ zdP0I|wYE0oUGnlyVt0rt*!j(g8=IIx%|u*SZ2n^SF7ybkt*vR68RdF=AA1vS*Zl7Z@-5v+|RJqpWoZ z$%}+B(w*HDKH!oZz7hPE`@!$;nY6=f6G|bOURx0G;bco4R6u+ialH1E9)Tr?@CZF! z7V*hM9)7TCB}02H#`fO0PTtVH%Qt%W1)a^?G@?MAYL@5pF_MH_NhpEwZhUh-E|Vvb zc#(@fyY$%QlV=XdiBSFFz~kW@Ef&`27z>%kZ>~lHfD3?3^Oyn3+5C;?r z_wmG2tV%Z!o%=K7#n!$q(ZLH$QX=t6SRJ%&lU&6dCZWrmJFBwMI;_~1}vI%sqPBXtLLP_&2*-j zB%ePf&zu`*rsJ!+Abqv-Am9oMg=*MwaDGJtmV)qiWV_mpQa{* z-BBr+RRR(>S+CNd5WV$IGd!0XrVIRGkUGO9(7QTW@UL8 zh0k8jwaBG&Xr1W(wXmKwXw<|mzApWrRN)a}{UAQ8sj=>1=PHok(~AGt^aRNtA%E$T zM+onT#Vj7z;SSjYndYZNA5QYO_87T$(l*_m{+s&jZY~^=t4O9%hz9#%qjr+)h-6Eu z%u;j5zY`~OA?)T(ZpO9}5c+^b#U}W?DthBh;l*K>9rHr{jn%rTYc(qw9TR#yP0=TI zJuyHD3w~jE$4^AYu-MdI$fJzSwldd(vvUjKH$?*r&8KqSwgnyqg#+GwKxmqIT{?X zrp+|Z)9AmLOw)Wmx8PhvSZJs@v6Tq*&&9On6Qe1or;^~r{1IVpDJaF>dsh`iyU6UzcF#f)~?A)Iw_1X7g3V?G4=tFk47+Z3o za?$g^!xDlU3=#AwUi(ZDtgcv<_0zGXQ zLg5}xc&2H1csR}jL`z4EGZPTw!EA7}rS^XK@NT)uF81HMZ^U}-!f#N{PXAak_k3_u zf}E;n(GEr*pNSm8;k<>pSp%ugSi9F#GINvCkA`z6@ZH<7^+4Kf2&miP1-8ctS{ewT z4&*zMeR)^KO?!3g%SbvP6_81koU6mU=ee=p?KgBsbjo8t{Oi{@%BI7Ckh%QI&l;rt zG!c1X;e;D)3ce{DNm#5|G$1)@ufk7KR}34Tyng-q#<9oo1egA=8C^XXV(3gP?})OQ zm@NOLA6_??UkUhl)C9o?UJ);_--0i~%v32rj-nf?R|bdXzk`gygzU+WtV_Z=I#r`) zHBOsLBFK}Av(o7=P#5X7!wriq3*yk`M!_uT3+TkQf*R^k)yW!-*H!yf;r(e{44RBm z80-L+_zNXPS$sULs{tUHNo8JdP3C&eImG$SYcyr8g z`X~vTu;WW)D3|+1NQ>9I%Vb{ZS?1p?dn{M-axx&S1^p%#Tw|ANO_D3f-?;qY2-S~B zP-TZS!7Jtz|nQz+XXTbdZ$&Ms-jAX?PGlAxO{RNh6Wu!qg%U} z=mH^f*!_JWrVpp1$n5Um4e`(;F=nEGjtRtdODnELK&4;t2Is`x3FIdz5TZ*y^SGQ`wwEmCM< z-MR(k=@*A?SgQm2_or{CNyhkpR#{k@H*tRVIp1@H_1ZN-I9ck?A9;PmDduqBax*Zf zh>u?f2_`tqK{f}*uiDeDR2U7Ogc`%HESXm6Jd=h=3J8{E&8ZF4b_wV?Sy{aXJA<}% zei-=UTy~>UfY7F)r47Ch@$)Ggv!88AS4$JCWM2ls)Y+B_nG^T~cl9?y&Y9%p6&o9c z+9d(&yvLoy&CPuug)c&{-QZex_J3w4zHq?))Lq_u|6OiS%9S7bi^2 z%}vNEZ110TJ{oW?7C0q#Dx5g)iRZ9?fx#}snVg`v8%ojD70YG|ncdh{gdA?N>zTxS zyf1VxGgu-!3aF?`i@UpNMDXLk@;apy7A`L{)G}dwxo3JF%s+s-wTY^p9@IWsJEi!L1!8quu?w*}QRLBV@P&6`mIMItmKH0uaP{1*$agvZs`Q;r zaV*@N;80+jbjv6&--SIyk;uQcHcu!ipLpJOer0@R#n0UpORVV*(Vel8o&hA1%}#JR zNtqc&s5V@1JS^E&K=grq??eO7qdKX?nBa=^Y4oj)9lL>A-`){WF8v!}Qp5Z64`Cv_ zH?4gBi(0J++#MP!GO?l2IW=VSxB~|`Vr*noV8V{(viz9jFy?knDzg&VIS;U3u!-kT z4!IXeNZeYSOv$Z3x0`KO@Fnjk3z4G79Pg3|d|0GgVp&x>*~2LGUUem}n6(GRD=4ry zTHsLsxjUyLXTH5@;2r)(@uB1kzcV(t7#3Gov$Aps+8gAEy8M@&&2v_v;1qsBcsXIi zVNF<1{-DQ5H(kqV9Ai479v23lX6;*lJaD>jM0OVXe`JdLzh|%eKYFKf%0M~50vUO1 zkKX-V0yjpuCy59-%15_k|9mhajGFa&^Z0yRC0HaZjqr6U76z+K5D&N^66! zKO(wT!Gr3bBUWZGJ~+n2BD%29G5VHw3yc^eEvM+&L6Txzm&|>6)L2^jxrDv>zwAF< z1Xk%lU993j4M(_E&sMlE`OHCo?V0(Asw39^MbKU}8*Nt8YcsRAHNQ4kddKTT;)}1zJtS?x&cxf5BJw*EaLBk=% zdnQWra&Z5|@EBHTuJ<94(Gf~kI~$_N z3g82Q(%aeJA2tdb8Y%%z%)R@FSLN}w>!x{@RkoGV_)e~_;o*uc$gq=_nHOBTy@P|t z$xj?FOj2&{0igU(2OUd7CMRneyd`Nh85x*t-{D)8xt57xl6aFvGvfPi9jaG2b(U0u zHW`G;fUC^CR#jE4Ju`9DvYg7wGrxZ8Mi46?^2!BvXW+i(?|&nTX|Ps>XEUOjlL{W> z^~r`Me8PBR??uDxOVjt=;J597!l) z=b~~=95v%~J9sZ&URf?0_U-jgGts-iQ0=<78yFn`R&_F5d93{0UjPT zK->aE8BQImXaw6J25NUj#mBw^A5dP~=Rms2_wOMunx|)G=x88PdCzWtBw}HrV!O1~ za^zPI>7fhhn`LF(ZQ;Ay3nL zf7)rkT4@!>ag`Iy>uPFpo~L6u!13eI$K1t#KsyIwIp#6{W@7^1f&S^kuF5>|xESZH z1C_=;3Y~=6OTvLM6*h+zv;ktD)XGir?|JOh8`w9Voq0sAFD`~3w)b$`FO06c$V`)GBsJhUFwReJ)!u(s|kA9u$Y94rR!jb9k(VqSGXjw`Pnm&pcX+Wvpdon=(j4V&&!A5oOBkQ7uv z1VyBgRFM|xF6l1m<`ETXsSQY}l(6Y$lZtdocXxNgKKBNnSu^XrGjnF0^Wp5Z{35mE zA9q~W@5(S2c75Sny5_}cdU6Gd?$jaCm22kgwkR6#oM1{M8$aTA=aK1(%q5y>jiX_K z2AxQAq>i5-VxG&W@=TV8z%9)xyX!s- z6U3j*agFylm1=S$!jLVDn%T49p~=g{yL2fnB}0CuEA;Ev@;_e1)&rCXF%QEK2le#D ztc5E~HxYQBo9}#mrV^vDB=gnB?~*$-2LQAHu{%(UL6VM!KK5RR#}Nu@?_;-eoxvcd z-keN}^7576x#y0~o!+@x@w|q<1&2g2FdkfEn;`DD*D)0LQq49F(#Yhu-gh2qqo{lEnL8u zsxsDo3BWZT7|PMROzlEPSHLrzi0Ws4E^KNl=c*pR-%uwaDJGUh@FMi8-NWlgWqhQN zGL|C&wWWDNN{ZgTU-YN8*C&0H$4re*v0$|jGyas73M42WX-h~9^>q-zWO;mC8wP%W zqHzc5H3(_IRI8zE^xlm8QVQ_9Yz16(pj`FF5d*Tt#R=HMK_RFPcxNpw?|NOamww?t zp%C-W+woZ!!+F-7uBogh=LEgRvwV=(qPMv-L7#lIytC5T)rBOmmZwaA13K{PelHpt z8YXajX05h;{@mXiaX-??Vg)lfW=x6Xl10-Pd!eWw@i^gR5)H5|jeojL`SZ!i2?acmDb=!~MZU3Wj~UIB^u z4wnh;e4W*HQ?(V2Rn9F(JUmY7-@At$777_E*RGMK1r!=HN7C4ET8@72|ANe2fW=an z3&wP$Ap`VD)X{)?)pASPBjrXDllcb?Na{!RbuSs|=olZ-b32UoruB8emDbEc7kx}c zb&LJvwX{&5__(=um}EQP_xzOfJm`#2;KlG2|}=1Ugzt@#K&lPR=BY1nvL0BefEojaM<6 zkJO2ud|dI_py}c1Y1(Oy6izEEG%a|*ez5Pi#a{zO**0g|h1voJ?%H10_;26ltwvDm zPp{GVy}_lTxmqO?H_3(i&B58m57%Pk;mf2m9bYaAJxBbuzIpOmV&wx$1*g3KQFu6% zdiwF11&}|PTjB4f%{nb~4AxxElf$?|@^G2>i>^wr~i+>=}~+qC=SwJ zC3jtUJ6fy{_ULoxfKYHUSK>(*!eyi$vb6dgVvhCZW?k`ZgLfzIfP;#Egr=b_*ZE4` zXpoe`u#T1N$>^6A?AKl_C*KgOuaaa~#(LEcAHr@7SY05AIlU?p|71E-yJxLPKD_=nE2-Y_ zTV*DuAm}iSMa|5P%FBeg`nkh|spe|L88gF{eCJb1VV`c)K@0P|K3dgKO)(`05nwC` zxP~-|x8xYEkw@+|R-mg)PhUvo?SM<1HT^_Ye-|c}<{70!2c@>k!Ilr#Q^-yO5>iF! z+8o z1hSJi0k?5YQkrDWhz@_T=@bWOIKZlHAwl@CTEHSs#2MP`!BM56nkX@hCYsyp9`N^f+rqA$fj`42Xy<3$^ zZ*uZ6RI*H3{Y8$DX8&-Rll)17p_p+nSgIV_5au6Ycd^E+!ry-7LCcxbc*JofbBb<_-yB=KVURaWZdc{t5^X7Wb4!``) z^7uFBm7YvdPrxofj&+d#jX^rNYj3T?)^Tj-U{cKa_-&+yhDJ^m;H)8NPaId58(UH` zaOAin3emy`{_81x3eI-7WMajG^Xm((YPWf}tvHK9$z`Dymf?Ka6^0N5$Ilxzv70PO`ts({Wg zF)~_OSPIz$*%aNDE#9rAn4IQ_-up%!FtPLGTYzVe zQHQD4^?OP85f7^bhtd=dIzsH(6lCsWxINP$HGv^*Ujh2PJ-#%N@8nNY2g~aD`9&W; zpHG3v;^O=tDo6^?rqFPC3OmkOxfAnHx59qVz51Izt^Q=6|WieGQ(f{)0jjlbo5thxbK4oBKZ*Oh&TlD7R zywsK9Su$YgpzZ|Kg2O9i7#FHqGT?KCtvCr~l)KCwD1iuaN{ z+O0anM)JgF^d0q8nFnXQ%nmRPDx3JCqL)iIwfM>Bltk`t^wEw$h0@?6W%<>Bl+cwfXaO69OzjgVZ=5w|QsWdIG{OIMAGjKJ{>QGj0+5JiyRqasL z?~-{vuE&obi$#G=G*Y9~vWva5dQHb5JX7fk(T;58o&5PGKp0Yw!cbP0f|~WAQqqO= zoz#!hN!>Lc?s?OPX2T|5u>CSlMxnsT-RNRv6{+p`*%Xy-C)Pq82{=jmz%NOt zZdClKhS!@>V(;CTRKFpP)n0mYMa}W9K z$KQa@u&5{jZ$V;NI@Lp-Ul{%HqT+=*Pz{-wn{Vyx3~kQ$udk=BX0^fP9wu+1*F%LN z>F52sU%MacvNVsT^T8+V`J=;B!L+adCI}68B$^{{5Z*FpkF274F5D*v3hsAQ;FYg$ zETPg8Zr`=qhWy~AH>;O#Hq$et+<$mKI}-&0l%Kyk6*Wh0PYv_Iit6gUkU4;X{b?_d zwOcpBf`q1sQOa~Il5&$CR7e>->XXev=jc(Au{=cCz;R)!H5Ote$V`o@NQTF{R| zRrgO1Unk%lvtIn5922n;7G?JS=;)lLYq2X_u>t9j;p7T6{x9+Z)939Wb>CMfCx5}) zXhdgJ=NBp4wbX0z!ghZX*tKnyUpxklLiDop5_rIg(LLH(Zw=Fa5`MlrcX>>uDy_?ETl(0)L#Y)hIAdnJR_Zt&D~U|4z>d`wDk) zl09Ym0F+*3b8}b6=ifGFmLi7d9 zYIc@*`(YTbrJb5U2JhbX+z0I)7sQ2Ns?4;c*-M2D4-Vr&3QDXHa6J~pQ2Ac#^$9p74R{gvv%AuyVnLy^SU00}5KCq4l!g6>>KJc2l zsuJ_+Osu*~73R;38ci2@c$SknB(33LDp8MQlAhD)!~a|2nPg{Zin45yekvfO)StL7 z=d2U|TZ!AC^QFre7!HUqd7h-DllhFt1*c%l+#3d;;3{ZnD%&HiwxV`|;dfuPAnk^J zZhL2M-ciXASU0Mzpi%@)_CxOd#SjJ`0VCE1kj;Jg>pm-|pE zU%@v5<2AsnoEG@8(X=kUV)9)>$D{#EMPJ24 zC4%P=7Iy6HtSK}rNBi;w1omjGk?fIIpk)DJvtRocIH(5@lphc#tO!1;D$>M;;a`4o zk?id37eM9o*FGCt0jDve4v&Yh@{Y9K>9NteMSTum6tJN`lU_CllMINE<4;aar3@pq zAN1`VmCw#zRDBH_GA@%>8DRJnil19t8Q(tA&1P#+u3#74W&UTp$ZRS^nB!TUxG zzrDG6tBRmJE1lZ{s)osT6SXaJa&i_XU+CC)w1;(AdAt>)5ZpomzC5D;CWF@w08&9aumzpY4c`k=2 z(!$Irgph`YM2_w8>)=6yk#ef}beeh9;ldpeX|0t0^(_v~&N&?8v{2*=}v$T0P+sF&HN-yiE9JJJQF<>ft(mxl3)(dxRK_~d7`?RNdLVSv-Z zDpK^Rhr6s!t{R#QH}=GEzY|8U$Wiu!;!QJS`0N{bNHvpDSAU>*08*?1f7*LBqEP^9 ziFx&aD{Bk%mV45;ziQF2X3?-KgWTvAme^I9%v?d3m9@p=JcslZ#`=<(%cL z3ye=b?%xFYQY2Kv2mR7JC;pVu7*s#D_v1-3^WLI{p`oSnRMZDhR)HBCu5fm?T?4~8 z?}!T2i$vdRWVVR+-=&l@HV$@?3NChVD5}V^izF{{c_<-aA0M)w(=a`a$XfjbnmW;g z^>uo0gzgHXxmr5rdVsYW!8@iZM?Ha2&t`8=XALC+q;K*TVEr9`9Vont;iLqPWcZpz zX|c47hmX(vh5=)KK>;#f9MRHYoDUO7NH+_pWi9`tA~OU>wQ z0XHOXb1nRlMo9H+#Krov)X!!s(92;SPb;8T0D~L2pu}^x@clu=w6?Y#{PJsVt_grA z&z(zZSK@xnSMY(KwT`)8k7$L1bl3^r7r=Gsy}C}RVFUT9FWuQb75I;JK9KQ zy(@e`^)o}^*vmL3y`R72ly~gh#=fM&%f6RP-4e@vR9PP1;3*Ql2BCvApM&-kHPmVA z-@6n*NHT22u6?;d7`8m*sx*|O?RdLo%9rRNWoI5q2rmy0g+tV-s3&k%6q~%joD>M} zZ$ux8dNtkO`9P|^@l(e39X`&pP_Mg+2XV&}Q6Sk*c@hG)vf$wHDLv=A-f?k(FCl`u z>nqpGdm)K!Beezl=~4Ek8xS`OEezIfrIYSC2>%uT*SMKNXIh7|UKg7&(lNZwbw4k;oC5z%JAl@|w95fw{8wXmF$)Llj#B4C$f^R(J(8(V1^ zL7Ltx14p|>cp8gj10(UkaWv2b6S^BPuulp4E0JZuPbDqO!ehai7GUcT?qa48yy zd$D(~!04bLp7aG@$YJT*wR&%5Wnh#3-2z%&0O$O93CXm;wp1>WlXyhkBXwZ-z3>~b zpITSk(1^sW_BSPBFXVea6aDO5oVWubVJj|%v$Avzqrfu?LKhD#epQ1DQTtAfO35H} z^}>(IVuTOr7Aof5JI?BMBkiXWTBhx^)S4wuCV6E_BWZ_F8QJ!GIpa2b^`s4;&Qcbm~#fn_*1+(uK!Qlzm z5KIK~O)4|X*OhXzvI}Elv1~?fAI5S!8yQB8Yl|zs2l|6*{dl6aru&4T1tp_5J2m6# z+LpPQk?hX>3+%SWi2bzd&M+(mx+wHb?&t*rO4rr*`~7=IeAT3uJg*u3n_(t5oMhJ4 z5!(5yaAYWymCwykUS9zv6yM3A^p;>t6eT)Qn<5XLzGqHYPz0g)rSUhJRzmvy5E-s3 z>{z%gqAjo4b34vb&IVYn@Ti>F{8ck5ReLi(JK%?wqfFZVsM5d@oy>PWm8qHer6m(X z!%LSgIn0zv2ny=K+5lt)pg_GBLdRe6lr);h%6!k~{6cqTmS1RJckE~O;f{{@Ntrl$x1ddwb9bocE14 zfkuuojqpu+JVlRwy6tTXf8(?orbvdf^}F&1-g^8r`*^i%Y;uIkg0;MHm$MQ@OSgqx zhFZQzMp;P6_0C|>S70Dje81y?_EI+{%cB1>+gA0H@1ej2hMmCgh58X*gI}eUrK#v3 z`Li(}$zk^1K5EFMWGZR}2rDGSvvItA!Ll~Cb{1&!a0q+pB`F)GVKR#TMLzE{)1s~r zH>S;a@19Kd@Ku)YrNHXG!}N&d!BNwkZ~XF98j$4jz{uEeTQ6iZiPR6(xcv(!IgE6DDq{>SY_|l>o zOu)0VT{+6R{KqHDV@_&O6+!WB?Wt4Q07wGg9Z{u^Jpw5K(T77#sg~`4T=bz899AA|!b8{c6g!8hLqm50)=aoGVZ8z_G1lrXW~RRS$!+dW$&W=I@Lxax{zW_RFGvAOAgYYI zG1^znae^?8)epGLiH-g5{{#OrXOq6Qdqt3D@!DdLMZQbn6d9;t;SsCw$Y-LCaP+A= zKfm>9MXpKg>37-{{kKDLX{;!we`W!g-}c}B!2i`ZJ!)Wlz)bG~JNj)JNOOY};kRa( zJs0fh53qqeoR;?e&n#YORr~^ZYC}WG--5cjyH#wv%CPS(!;J;{pic-O5;s;YAum)O z^K7sxiFqPDCQh*l#uoUI)32gTk-^o^@Ir+@MY3ttG^IRxgeWv(j{@~wf%#A$FpPM@ zSXG*XX*P7U zw#EnashzLL4PI$}A`zatHFsS`cfTuq1VC@8G!+L&1F!;s1$zKWy;^Xk9YB=~#$eK< z4fP7$bn1uu8fDDYtG9l_UAUuh~r}MId)Z zqYf&HtBx!(9an$4`ZvX=;Q%mnqW&*(PjjAZ|2y<72yWTClv^z~!otI!l`&K+tV6K{ z{2a65r!RDSp)i2rgN+olyi32EG9n_7QLZrYA;GG-m0bC8Q3NxA>^|k#_jV}K+gTc zgYIgJmw?qfhVYO&_u+9=6Zj&>mh3gX1H5I#F(Xs%er|AbOw}Fi?;r0U)5;VXt_@n@ zfScPK9HCQ$@)#0D(zQ3yppi#!Clhqq()jKztqeb6%p6=BdbEW%JvD@nj}Nz*PyILn`#0R#QO8Qj>PA|@}3X-Et*}#|C&U}^+4&HbU;*#-kW`CjF zwM4dHo9{GiUHL%uG0oRN0{;PM(jZa(lAbQ{Xa(*bifL-(6j$lxxzgK;ijOu`QC=k_ zp&}_wC7?9PVA2yqP+tX2fe%~MC(g>(k3syw*2y8}k_Cu>c}`O13XpsBiOcH93J8S! zXuQoGrcS_%QK-WHAgBG(!O!jO0C)6;Fy-M9i!ERgE?}P*(T4G*ikxn}HnpRu1X*U+ zJRHlqOyK;l_D6QryosJagG`IzV_oj%NG$)6m#6zA3x&e&^KCM9nLED~LBp$DsvEl~ zjxThVU~B2rK+jX{Hb;TkIt~;px`blu*dO*r)_u%s%lZUy)A=PO$)#!Qn{$|o*mwz& zX{YGXe`wU0H8AiH5kCX@dU+83nka{*-RzF}LpYZ7FeawXnb@Y!ybM$<;L^Sa*utp? zH|sUrdW#j8$e8a?*&ZJ%U!!yZz0^UvXwL1gqShOd94&@<2()b45ognm{mY^C=74#6 z@vLibQ;Q%T85lSKfen3g!eqKV`}_A^AX|~Q-+2m)bxoaSL*RPHMF(>_FK@cS)Xh~C zpzM|q78DuzguADsN?_(2*(~MhJja2acaMn^JKOKaRa-!e&tI1hjmyl9-vICtt-oXh zyK7EnW-BNZ97Ut=eEp!kq^fm7w}x@1jg1W{ZmiDWE}Yn%Bo-Eo_4gol%S_TXY_tmD z`aOmXsJdO9m8`FGZtmmte?}q`bp$Ka->%M^Fk=68*tvM*j#j#5fN|3UInLxhRfn|! zW6InIPN&I92+Nq5sJ&q+(jA{frVT4_5I29oZglw(GY%vu*`!x*tnEvzcvpU9v;3Kp z6ed3!l}c-smnNS9CA=e)q~Mi}WU*$>y?5g#0;V%XMMZgozSMGNW=k+<*W{1OHZ52g z){%h72fcot!S9Kr=|VXKk;+Ae0j|ZqZmYGAN+5W`&8`HY3!LH?`qx5g>O0xZ>pbdp zO|I*kNr9T>fpl)*=%=T8xc%H*rW?Vfb&ooo9mRYap|*+%4i1fpxswUP|0=HlqMMSmtWWgZnSYoCX!_4+sICTeNxYG|b3 z)?cVuJ!&*pen;7}A}(F0cH@dS~x{kTj3E?chU0-6Wn#4Fl79*E$UL~enn33VutB#!Td)3gA74}_nfPsN7+z7d) zuB$5{g}kSq0I#yANBAz`0pY^@!;#dqMehYoHJak4X0kmv@k9R-Ms~dr7N$SB!}6rZ zA}Gk`&uJ5y(BgXyegml>%;Sm4$#{wV>j^G@gnjxIs+6N}H$+zFH zhZVJl8 zd{(~R{{gf$Wu>LsI`Py=Pps!lL%rT(H}XSfifO24=pY6_`ZHjCT?_`dJe1^H;-pwu z71S|N$Y+k1zMt_bh2xNB0-CK?5@eKwgm-)k&46q|0)SlV8yDgBL~q1mREHmA&Ua*7Y71PapW|ypN8toA!crS`AHhzXhC9eK5T*LxtKdYlR~2m+8yU@ z^3b~1vu7}%zm*<{Y)FFiM37Ntf1PV&tXNoHmL{8=)EAero*S1h*@>X!f24rV{P5wg z*Q=&xMhEM@X256DUQ&U@Eln+z>ISQWh#eK3kg)I!94l`Q0ls3KY63%(swx4v1NsR~ zl$UwYrx&6^!{jk*MBs~_Ik>P}-wl^~i#7+EEZP)A{jVc#EDzdNdH(LP_A{WQ!7M-; zI;f!*d}g2WeZuN~;B8QFugt3`s`8tr-TwRS3k>d60143r_i~FzJ`?!~zLxUn(={eF zuavI8L2V9ML|MFRx;MaxMzL&OMbVzcsv;pGVhMd*R+VmDMhObFBu;(Bachgn*H_Hm ztwJ%Nc*Kw##kf^NUeAV|?)#O8hqv~a<_y;BzwFVMwTjRxOavN5nL&L8Nk2leSwM=P z30K%k#!9|Xsnt3R#UtP;2(Bxs9DPoQ`LOillx!p>-=!frIN;_+na>dQ#$NUn#t5}N zl7Wa0wYmYUFL>xNn+(pgg6noH2Ekj1jll6u-<=`JYl?l2M>3%hyBLzeNJuWtp}v}L|!_mH>;AT zefs^TZU=!##MZcvBf5TcEO|7@)~@i-VYec-yi|}+#lL3plb^uMw6PQx58(O%`~%M* zmQ}GV`7D;@W41x5n=QLr{etN6RC~qIi|e9Ew9S-{w+O>EZRGgzYeq583G214zMh)R zwofry@qEC&xKx*d0Mg>H)Aq?j3nr&bRL&u9YXy!>)8jVcr^)|>wfI#&L>rJ&@{9kN zxD%J|@)LjV*R#`Pm&&@POXqy~_z7;ry?fA=3%aLPm>wn>ewk)x|^sRJ~$iK*F%YL4^u+(QL3=njKL zh1lriyQ4}KTJq3+l)ibBOS33N-rUv924};`K4Fx|W^5myu@x(_*ugq^{pABB%4xkl z{OG8xA!Onkk5OQLkC1-%I}(;;RFTqfQlF{0sbN3L)!pHj@=jKKh=usHQSr`aNq?tI%bl z<;M{%T1LZFy*(tl39nHfEsg9Fb#ykE7@k1e<&IjyTa#99e2i}H;kF5V6Jj)4nNp!q zVV(6AQaxv;%CD1rrk|2=SR717S6SFOp$;0x?GKI{^9K&l8gAwRf_n2bCniWLzUi>;W&mILihO;xl1btd`amQ3# zaZyp)moG(yg^c$(S0Nbew54=t%9vaVGBW-djWa>i(3Ji&-q=x5a=~llu%qkHHKbkP z#k&NTtqHWLYGT@czn7|;=71C@$IQ}j`72SH59S3$caB`FN${gmV30BTC0uYcSmL? zKF`L#-2S^Oq2OxF5W}_ZI=@A^2AT;=D=P_~C=D5_xlGODhO~%~34>IIndwrtNBiD* zyla!rmU0SmalF<{v>d9_dO|k|FNgv;y(6>yu;6RCG{fG|$_NOY2rjOg7#mAdM4p%m z2&B2i!W5Fj=yQ#JHJ_a1(Lak#Mo`71+Elr3&yDM?9d0d=(248btC)Q^dGXw}WhX2w z+#U=sU?Kdll_f_rNYFx{ZH$F76&YQYBcD_;wE4`T&Y_;@cykUp)dg5qcIwB+{`qJ& zI(De4TUi}P#fF!E=2%-NmD5Fq)tC^W8`J7DMRT*hBm}2621|(GGMN@P#g*<>zgzPi z)<9=6^D{ZtyQ4SrSriM>A`aY1j$Eho%ZjY}(Bk@hBWwI3YVDmecW_!t2kocSA4VUO zJ)xh%aa=#+#R;OsjWdH7P1Fr>CpjxI6~=78r_qSH`cU}entPZI&M4k8IMtv^j zIhQ)Wo6cV3olzdOx%H>MRk>+=nKUeAH&bp1?VLPcQdRnwx8vqfE#y!FLmi zd->WmqPh^5n{Y%gcj?Qrbl01Nu9tq(VQv;vPes%U>epw7DQGBA=(-Hz+Ulz{-N51G zD*1fw=v!EFW$s~wk~anQt=`>sQg58jYxSgE8^`!dB>g$*0QOOn9xxubX-7KUH)L=Yya|GF!- zr@UQiy7#=E5Wt7FQ#mvQmjf@VS7_Nnivw&)m>&taP5`Nxlq@RI`1q|dY<9)EmJXlW zs^ie{?Z3{|UOJaER^7E`#RQO686L#od7+l&m<8D)ou-1 z;M7xVI4=470|2@hP~|9XclQd@+~nGIJYR4BV4V=o>8MQmI&Dau>g=Ru(>l3_@Ju!7 zcl03#bf*;=%Q9=usPme|x$VTYs2|zYBuE6^L5$t-X=v3;%*bkqE=(uB9%MDPA28ib zUmO}*{kEM&fWvKWI*|D&&aF`O8(w_2LG9mY35G!YxG&}mEY2&bx=CM))AGygwAZyGcPw{;j0BtgL#=WprvLW&ywK1Ka*U~ZNBXk? zTZ|bpX(V1vrUTTOx?{SI4Lpl9}`Xh&hABvaDO#x$Rm3tWD5AvrED->4Tqc?UT? z+f$L?8b{nY^LP4c`>tS*#Y(0H{VSiSM}5CIN{+*~TWY{@OG$v{P>o9K)VpTsa=7Fk z9eE@M1?b`UbpZ~FS)xQG9sI~AZd$qNE^tmVwt8f`AGY3#@z2PJ9a%bHl;O0WAD{{o z*LriuFwH+POtCXaSeS@3^mYf80e>u~ zThK4ohLF|CbND!H)cu$kx2Bm%eQx%NE8stC5Jz@^$+a~)G9;4iE9B__r}XE0#B{fo zBF@ECRe**k|BzKD=elhO;CwT;*Odvw@4i9%QrNt+sl;_QCBNJafn^Fb3{Q5#8#mf4 z^3t>yS&s9XkN=Jre$^5Y`2feaR5yy~k=hgIeGu!w!(l$9RZ`mPMt)>y0Z0c^R9GkM zSIT!SRPE4=13PGRqD%8n^zZJ=RBT$y{nh9k^sj?pVUgLa*ZY|SvHJsG{97aU^`-Y5 zmDQ(NWD#O4{#y!HEd)kaG>$|XDu#9{8nmHGka%#cST?M#QH5wcj9NI3S~Nu0?+}_i zUt9Kd55OtJP55+!!)&d|oy%$YI*#TWW)2Y16~ZjUF2n=(?E8)l`MJrtk-UdsPkMRkd$OgJc~7Y zb@1q!UJ-42Zbsp=Mv7Rcf$>3xBKKEw~APLJkW!zKLCBpx=&Rlbff~fdsEGVTc3!52KH} ze+$~!B!G3lUKeG%QNa2y!pk%=ElgHErGldq*3BuPqV@Lob=&lm9#Iq%(*|d&*4S4z zw)|`+X=aF3v0DH2_>331x64IX1Y1oA#cHesLkz)t0JEMB`iNWLZrzKi`_j_dtE*{X zjtvS5Q4VUU-N}he?0p6f@6a3Jx43LvUcbIgXEZoT7umkp5JndMNG%K#5C|3=fMf!} zPn4sfkwKlOb2x6^fqcim!OC4&=79b{9>rBszCW%S2_THAX%+1N00Y?O1(gis4T!+> zaiNFdw~#{jyUooT=?cyOiE0mibK1e;&fxg{_==zRwM9`uf#8;m+$}q~824FKxkV7D z&Z(;}7%wzK79y;Cr^e=n!O&O|A~?0MV7AH(V{qWHa0Y<+3&3L~xs>uYN~Hex?sGmJ zkAR%C^O8)M{*m)6w9u8ZvugoA&VYoW+V*F!!I@`d#3j@xAzKrPbs{sHFUnL;7A# z{0DL_4n@ziqgPL8uW+`lCKS)}5@LB&i8g2{ph{FF)pkphGph!!%uWz~8@(!$XEoY6 z!oIQ#o;N!~RuzARg-;#=82>!<-UO1ZZaNj9f}~;^IdY%=ZM@PlG*Xw={h83y;0yHP zJR7|CLL4h~Nk64%E3AHE^-+lLFt%mRPaspkcf23*2O}Y5vvPJYp-bg}%#!Y?j@8HI zlMma76nTjG{X^u*JFt4Y`=bDoNqN7`h;ZM6hu%M*(rbFT6oXmCJXW7}&!h}4nT=+d ztj|Pw@(Z1`(=$n9;V-aur>>aslsUWvKcYwO@71^-=qfPgbgb1IcVNXjI(G6qIIo|* zf`#<~6Xl9|oMyCEb_BYCzMTj17T^Qy@VE$Za>CF5`IcDBllL&dQhy5L7!D`QGXa(N2e-*`!uai8+z>U!8_x#T=XAw50#W{yXIk9HY T*sQM%|APf+wHF!BU%&ldUJ6UM literal 0 HcmV?d00001 diff --git a/static/images/accessanalyzer/2601/migration/add-service-account-client-secret.png b/static/images/accessanalyzer/2601/migration/add-service-account-client-secret.png new file mode 100644 index 0000000000000000000000000000000000000000..43524a22162e1a13efa3afe53c40dd043e6f2aec GIT binary patch literal 128026 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⁢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

GGUs}y9QsPqmtUg_(#^E&vy@kE~ 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 MO9^H_d-eW*0c8UssQ>@~ literal 0 HcmV?d00001 diff --git a/static/images/accessanalyzer/2601/migration/add-service-account-form.png b/static/images/accessanalyzer/2601/migration/add-service-account-form.png new file mode 100644 index 0000000000000000000000000000000000000000..c045f9e008a81d8b32fcf9f4018293bed20863e1 GIT binary patch literal 129106 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

3Qkp`^iym!Ekc(>66)>tj-BDbq~h6YT^DBwSnE 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

ylg1N2+tzH!p{h&LZxL9K) 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

ylg1N2+tzH!p{h&LZxL9K) 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

3Qkp`^iym!Ekc(>66)>tj-BDbq~h6YT^DBwSnE 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 h1pl~qo$_y^L6bi;O34rPgRh`LL}lL{Q-Ao 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�Cd_+M{jJ1Ge-uemC!X`hP9w6PIZ(2=zhnu(K> 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

fpm6AP)XU4}7E(HaA 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