diff --git a/docs/enterprise-config.md b/docs/enterprise-config.md index 0e8591f60..43eb5594a 100644 --- a/docs/enterprise-config.md +++ b/docs/enterprise-config.md @@ -43,6 +43,34 @@ those of the [Git configuration][config] settings. The type of each registry key can be either `REG_SZ` (string) or `REG_DWORD` (integer). +### Group Policy templates + +Windows Group Policy Administrative Templates (ADMX/ADML) for GCM are available +in the [`src/windows/policy-templates`][policy-templates] directory. Copy the +files to the local or domain policy definitions folder: + +**Local machine:** + +```text +GitCredentialManager.admx → %SystemRoot%\PolicyDefinitions\ +en-US\GitCredentialManager.adml → %SystemRoot%\PolicyDefinitions\en-US\ +``` + +**Domain (Active Directory):** + +```text +GitCredentialManager.admx → \\\SYSVOL\\Policies\PolicyDefinitions\ +en-US\GitCredentialManager.adml → \\\SYSVOL\\Policies\PolicyDefinitions\en-US\ +``` + +After installing the templates, GCM settings appear under +**Computer Configuration > Administrative Templates > Git Credential Manager** +in the Group Policy Management Editor. + +The templates are generated from the [Git configuration][config] reference using +the `generate-admx.ps1` script in the same directory. Re-run the script whenever +the documentation changes to keep the templates up to date. + ### 32-bit / x86 When running the 32-bit (x86) version of GCM on a 64-bit (x64 or ARM64) @@ -119,3 +147,4 @@ they will not be reflected in an already running process. [environment]: environment.md [config]: configuration.md +[policy-templates]: ../src/windows/policy-templates diff --git a/src/windows/policy-templates/GitCredentialManager.admx b/src/windows/policy-templates/GitCredentialManager.admx new file mode 100644 index 000000000..26d9d8f13 --- /dev/null +++ b/src/windows/policy-templates/GitCredentialManager.admx @@ -0,0 +1,538 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + auto + + + + + azure-repos + + + + + github + + + + + bitbucket + + + + + gitlab + + + + + generic + + + + + + + + + + + + + auto + + + + + msa + + + + + github + + + + + bitbucket + + + + + gitlab + + + + + basic + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + false + + + + + + + + + + + + + true + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + wincredman + + + + + dpapi + + + + + keychain + + + + + secretservice + + + + + gpg + + + + + cache + + + + + plaintext + + + + + none + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + auto + + + + + embedded + + + + + system + + + + + devicecode + + + + + + + + + + + + + true + + + + + false + + + + + + + + + + + + + true + + + + + false + + + + + + + + + + + + + false + + + + + true + + + + + + + + + + + + + pat + + + + + oauth + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/windows/policy-templates/en-US/GitCredentialManager.adml b/src/windows/policy-templates/en-US/GitCredentialManager.adml new file mode 100644 index 000000000..7b5504bef --- /dev/null +++ b/src/windows/policy-templates/en-US/GitCredentialManager.adml @@ -0,0 +1,686 @@ + + + Git Credential Manager Policy Settings + Group Policy settings for Git Credential Manager. + + + Git Credential Manager (any version) + Git Credential Manager + Trace2 + Tracing + Credential Storage + Authentication + Azure Repos + GitHub + Bitbucket + GitLab + General + Interactive + Permit or disable GCM from interacting with the user (showing GUI or TTY +prompts). If interaction is required but has been disabled, an error is returned. + +This can be helpful when using GCM in headless and unattended environments, such +as build servers, where it would be preferable to fail than to hang indefinitely +waiting for a non-existent user. + +To disable interactivity set this to false or 0. + +Corresponds to git config key: credential.interactive + Trace + Enables trace logging of all activities. +Configuring Git and GCM to trace to the same location is often desirable, and +GCM is compatible and cooperative with GIT_TRACE. + +Corresponds to git config key: credential.trace + Trace Secrets + Enables tracing of secret and sensitive information, which is by default masked +in trace output. Requires that credential.trace is also enabled. + +Corresponds to git config key: credential.traceSecrets + Trace Ms Auth + Enables inclusion of Microsoft Authentication library (MSAL) logs in GCM trace +output. Requires that credential.trace is also enabled. + +Corresponds to git config key: credential.traceMsAuth + Debug + Pauses execution of GCM at launch to wait for a debugger to be attached. + +Corresponds to git config key: credential.debug + Provider + Define the host provider to use when authenticating. + +auto (default): [automatic] (learn more (autodetect.md)) +azure-repos: Azure Repos +github: GitHub +bitbucket: Bitbucket +gitlab: GitLab (supports OAuth in browser, personal access token and Basic Authentication) +generic: Generic (any other provider not listed above) + +Automatic provider selection is based on the remote URL. + +This setting is typically used with a scoped URL to map a particular set of +remote URLs to providers, for example to mark a host as a GitHub Enterprise +instance. + +Corresponds to git config key: credential.provider + auto - [automatic] (learn more) + azure-repos - Azure Repos + github - GitHub + bitbucket - Bitbucket + gitlab - GitLab (supports OAuth in browser, personal access token and Basic Authentication) + generic - Generic (any other provider not listed above) + Authority + DEPRECATED. This setting is deprecated and should be replaced by credential.provider +with the corresponding provider ID value. + +See the migration guide (migration.md#gcm_authority) for more information. + +Select the host provider to use when authenticating by which authority is +supported by the providers. + +Authority: Provider(s) + +auto (default): [automatic] +msa, microsoft, microsoftaccount, aad, azure, azuredirectory, live, liveconnect, liveid: Azure Repos (supports Microsoft Authentication) +github: GitHub (supports GitHub Authentication) +bitbucket: Bitbucket.org (supports Basic Authentication and OAuth), Bitbucket Server (supports Basic Authentication) +gitlab: GitLab (supports OAuth in browser, personal access token and Basic Authentication) +basic, integrated, windows, kerberos, ntlm, tfs, sso: Generic (supports Basic and Windows Integrated Authentication) + +Corresponds to git config key: credential.authority + auto - [automatic] + msa - Azure Repos (supports Microsoft Authentication) + github - GitHub (supports GitHub Authentication) + bitbucket - Bitbucket.org (supports Basic Authentication and OAuth), Bitbucket Server (supports Basic Authentication) + gitlab - GitLab (supports OAuth in browser, personal access token and Basic Authentication) + basic - Generic (supports Basic and Windows Integrated Authentication) + Gui Prompt + Permit or disable GCM from presenting GUI prompts. If an equivalent terminal/ +text-based prompt is available, that will be shown instead. + +To disable all interactivity see credential.interactive (#credentialinteractive). + +Corresponds to git config key: credential.guiPrompt + Gui Software Rendering + Force the use of software rendering for GUI prompts. + +This is currently only applicable on Windows. + +Corresponds to git config key: credential.guiSoftwareRendering + Allow Unsafe Remotes + Allow transmitting credentials to unsafe remote URLs such as unencrypted HTTP +URLs. This setting is not recommended for general use and should only be used +when necessary. + +Defaults false (disallow unsafe remote URLs). + +Corresponds to git config key: credential.allowUnsafeRemotes + Auto Detect Timeout + Set the maximum length of time, in milliseconds, that GCM should wait for a +network response during host provider auto-detection probing. + +See auto-detection (autodetect.md) for more information. + +Note: Use a negative or zero value to disable probing altogether. + +Defaults to 2000 milliseconds (2 seconds). + +Corresponds to git config key: credential.autoDetectTimeout + Allow Windows Auth + Allow detection of Windows Integrated Authentication (WIA) support for generic +host providers. Setting this value to false will prevent the use of WIA and +force a basic authentication prompt when using the Generic host provider. + +Note: WIA is only supported on Windows. + +Note: WIA is an umbrella term for NTLM and Kerberos (and Negotiate). + +true (default): Permitted +false: Not permitted + +Corresponds to git config key: credential.allowWindowsAuth + true - Permitted + false - Not permitted + Http Proxy + DEPRECATED. This setting is deprecated and should be replaced by the +standard http.proxy Git configuration option (https://git-scm.com/docs/git-config#Documentation/git-config.txt-httpproxy). + +See HTTP Proxy (netconfig.md#http-proxy) for more information. + +Configure GCM to use the a proxy for network operations. + +Note: Git itself does not respect this setting; this affects GCM only. + +Corresponds to git config key: credential.httpProxy + Bitbucket Auth Modes + Override the available authentication modes presented during Bitbucket +authentication. If this option is not set, then the available authentication +modes will be automatically detected. + +Note: This setting only applies to Bitbucket.org, and not Server or DC +instances. + +Note: This setting supports multiple values separated by commas. + +(unset): Automatically detect modes +oauth: OAuth-based authentication +basic: Basic/PAT-based authentication + +Corresponds to git config key: credential.bitbucketAuthModes + Bitbucket Always Refresh Credentials + Forces GCM to ignore any existing stored Basic Auth or OAuth access tokens and +always run through the process to refresh the credentials before returning them +to Git. + +This is especially relevant to OAuth credentials. Bitbucket.org access tokens +expire after 2 hours, after that the refresh token must be used to get a new +access token. + +Enabling this option will improve performance when using Oauth2 and interacting +with Bitbucket.org if, on average, commits are done less frequently than every +2 hours. + +Enabling this option will decrease performance when using Basic Auth by +requiring the user the re-enter credentials every time. + +true, 1, yes, on : Always +false, 0, no, off_(default)_: Only when the credentials are found to be invalid + +Corresponds to git config key: credential.bitbucketAlwaysRefreshCredentials + true - Always + false - Only when the credentials are found to be invalid + Bitbucket Validate Stored Credentials + Forces GCM to validate any stored credentials before returning them to Git. It +does this by calling a REST API resource that requires authentication. + +Disabling this option reduces the HTTP traffic within GCM when it is retrieving +credentials. This may improve user performance, but will increase the number of +times Git remote calls fail to authenticate with the host and therefore require +the user to re-try the Git remote call. + +Enabling this option helps ensure Git is always provided with valid credentials. + +true, 1, yes, on_(default)_: Always +false, 0, no, off: Never + +Corresponds to git config key: credential.bitbucketValidateStoredCredentials + true - Always + false - Never + Bitbucket Data Center OAuth Client Id + To use OAuth with Bitbucket DC it is necessary to create an external, incoming +AppLink (https://confluence.atlassian.com/bitbucketserver/configure-an-incoming-link-1108483657.html). + +It is then necessary to configure the local GCM installation with both the OAuth +ClientId and +ClientSecret from +the AppLink. + +Corresponds to git config key: credential.bitbucketDataCenterOAuthClientId + Bitbucket Data Center OAuth Client Secret + To use OAuth with Bitbucket DC it is necessary to create an external, incoming +AppLink (https://confluence.atlassian.com/bitbucketserver/configure-an-incoming-link-1108483657.html). + +It is then necessary to configure the local GCM installation with both the OAuth +ClientId and +ClientSecret +from the AppLink. + +Corresponds to git config key: credential.bitbucketDataCenterOAuthClientSecret + GitHub Account Filtering + Enable or disable automatic account filtering for GitHub based on server hints +when there are multiple available accounts. This setting is only applicable to +GitHub.com with Enterprise Managed Users (https://docs.github.com/en/enterprise-cloud@latest/admin/identity-and-access-management/using-enterprise-managed-users-for-iam/about-enterprise-managed-users). + +true (default): Filter available accounts based on server hints. +false: Show all available accounts. + +Corresponds to git config key: credential.gitHubAccountFiltering + true - Filter available accounts based on server hints. + false - Show all available accounts. + GitHub Auth Modes + Override the available authentication modes presented during GitHub +authentication. If this option is not set, then the available authentication +modes will be automatically detected. + +Note: This setting supports multiple values separated by commas. + +(unset): Automatically detect modes +oauth: Expands to: browser, device +browser: OAuth authentication via a web browser (requires a GUI) +device: OAuth authentication with a device code +basic: Basic authentication using username and password +pat: Personal Access Token (pat)-based authentication + +Corresponds to git config key: credential.gitHubAuthModes + GitLab Auth Modes + Override the available authentication modes presented during GitLab +authentication. If this option is not set, then the available authentication +modes will be automatically detected. + +Note: This setting supports multiple values separated by commas. + +(unset): Automatically detect modes +browser: OAuth authentication via a web browser (requires a GUI) +basic: Basic authentication using username and password +pat: Personal Access Token (pat)-based authentication + +Corresponds to git config key: credential.gitLabAuthModes + Namespace + Use a custom namespace prefix for credentials read and written in the OS +credential store. Credentials will be stored in the format +{namespace}:{service}. + +Defaults to the value git. + +Corresponds to git config key: credential.namespace + Credential Store + Select the type of credential store to use on supported platforms. + +Default value on Windows is wincredman, on macOS is keychain, and is unset +on Linux. + +Note: See more information about configuring secret stores in +cred-stores (credstores.md). + +(unset): Windows: wincredman, macOS: keychain, Linux: (none): - +wincredman: Windows Credential Manager (not available over SSH).: Windows +dpapi: DPAPI protected files. Customize the DPAPI store location with credential.dpapiStorePath (#credentialdpapistorepath): Windows +keychain: macOS Keychain.: macOS +secretservice: freedesktop.org Secret Service API (https://specifications.freedesktop.org/secret-service-spec/) via libsecret (https://wiki.gnome.org/Projects/Libsecret) (requires a graphical interface to unlock secret collections).: Linux +gpg: Use GPG to store encrypted files that are compatible with the pass (https://www.passwordstore.org/) (requires GPG and pass to initialize the store).: macOS, Linux +cache: Git's built-in credential cache (https://git-scm.com/docs/git-credential-cache).: macOS, Linux +plaintext: Store credentials in plaintext files (UNSECURE). Customize the plaintext store location with credential.plaintextStorePath (#credentialplaintextstorepath).: Windows, macOS, Linux +none: Do not store credentials via GCM.: Windows, macOS, Linux + +Corresponds to git config key: credential.credentialStore + wincredman - Windows Credential Manager (not available over SSH). + dpapi - DPAPI protected files. Customize the DPAPI store location with credential.dpapiStorePath + keychain - macOS Keychain. + secretservice - freedesktop.org Secret Service API via libsecret (requires a graphical interface to unlock secret collections). + gpg - Use GPG to store encrypted files that are compatible with the pass (requires GPG and pass to initialize the store). + cache - Git's built-in credential cache. + plaintext - Store credentials in plaintext files (UNSECURE). Customize the plaintext store location with credential.plaintextStorePath. + none - Do not store credentials via GCM. + Cache Options + Pass options (https://git-scm.com/docs/git-credential-cache#_options) to the Git credential cache when +credential.credentialStore (#credentialcredentialstore) +is set to cache. This allows you to select a different amount +of time to cache credentials (the default is 900 seconds) by passing +"--timeout <seconds>". Use of other options like --socket is untested +and unsupported, but there's no reason it shouldn't work. + +Defaults to empty. + +Corresponds to git config key: credential.cacheOptions + Plaintext Store Path + Specify a custom directory to store plaintext credential files in when +credential.credentialStore (#credentialcredentialstore) is set to plaintext. + +Defaults to the value ~/.gcm/store or %USERPROFILE%\.gcm\store. + +Corresponds to git config key: credential.plaintextStorePath + Dpapi Store Path + Specify a custom directory to store DPAPI protected credential files in when +credential.credentialStore (#credentialcredentialstore) is set to dpapi. + +Defaults to the value %USERPROFILE%\.gcm\dpapi_store. + +Corresponds to git config key: credential.dpapiStorePath + Gpg Pass Store Path + Specify a custom directory to store GPG-encrypted pass (https://www.passwordstore.org/)-compatible credential files +in when credential.credentialStore (#credentialcredentialstore) is set to gpg. + +Defaults to the value ~/.password-store or %USERPROFILE%\.password-store. + +Corresponds to git config key: credential.gpgPassStorePath + Msauth Flow + Specify which authentication flow should be used when performing Microsoft +authentication and an interactive flow is required. + +Defaults to auto. + +Note: If credential.msauthUseBroker (#credentialmsauthusebroker-experimental) is set +to true and the operating system authentication broker is available, all flows +will be delegated to the broker. If both of those things are true, then the +value of credential.msauthFlow has no effect. + +auto (default): Select the best option depending on the current environment and platform. +embedded: Show a window with embedded web view control. +system: Open the user's default web browser. +devicecode: Show a device code. + +Corresponds to git config key: credential.msauthFlow + auto - Select the best option depending on the current environment and platform. + embedded - Show a window with embedded web view control. + system - Open the user's default web browser. + devicecode - Show a device code. + Msauth Use Broker + Use the operating system account manager where available. + +Defaults to false. In certain cloud hosted environments when using a work or +school account, such as Microsoft DevBox (https://azure.microsoft.com/en-us/products/dev-box), the default is true. + +These defaults are subject to change in the future. + +_Note: before you enable this option on Windows, please review the +Windows Broker (windows-broker.md) details for what this means to your local Windows user +account._ + +true: Use the operating system account manager as an authentication broker. +false (default): Do not use the broker. + +Corresponds to git config key: credential.msauthUseBroker + true - Use the operating system account manager as an authentication broker. + false - Do not use the broker. + Msauth Use Default Account + Use the current operating system account by default when the broker is enabled. + +Defaults to false. In certain cloud hosted environments when using a work or +school account, such as Microsoft DevBox (https://azure.microsoft.com/en-us/products/dev-box), the default is true. + +These defaults are subject to change in the future. + +true: Use the current operating system account by default. +false (default): Do not assume any account to use by default. + +Corresponds to git config key: credential.msauthUseDefaultAccount + true - Use the current operating system account by default. + false - Do not assume any account to use by default. + Use Http Path + Tells Git to pass the entire repository URL, rather than just the hostname, when +calling out to a credential provider. (This setting +comes from Git itself (https://git-scm.com/docs/gitcredentials/#Documentation/gitcredentials.txt-useHttpPath), not GCM.) + +Defaults to false. + +Note: GCM sets this value to true for dev.azure.com (Azure Repos) hosts +after installation by default. + +This is because dev.azure.com alone is not enough information to determine the +correct Azure authentication authority - we require a part of the path. The +fallout of this is that for dev.azure.com remote URLs we do not support +storing credentials against the full-path. We always store against the +dev.azure.com/org-name stub. + +In order to use Azure Repos and store credentials against a full-path URL, you +must use the org-name.visualstudio.com remote URL format instead. + +false (default): Git will use only user and hostname to look up credentials. +true: Git will use the full repository URL to look up credentials. + +Corresponds to git config key: credential.useHttpPath + false - Git will use only user and hostname to look up credentials. + true - Git will use the full repository URL to look up credentials. + Azrepos Credential Type + Specify the type of credential the Azure Repos host provider should return. + +Defaults to the value pat. In certain cloud hosted environments when using a +work or school account, such as Microsoft DevBox (https://azure.microsoft.com/en-us/products/dev-box), the default value is +oauth. + +pat: Azure DevOps personal access tokens +oauth: Microsoft identity OAuth tokens (AAD or MSA tokens) + +Here is more information about Azure Access tokens (azrepos-users-and-tokens.md). + +Corresponds to git config key: credential.azreposCredentialType + pat - Azure DevOps personal access tokens + oauth - Microsoft identity OAuth tokens (AAD or MSA tokens) + Azrepos Managed Identity + Use a Managed Identity (https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview) to authenticate with Azure Repos. + +The value system will tell GCM to use the system-assigned Managed Identity. + +To specify a user-assigned Managed Identity, use the format id://{clientId} +where {clientId} is the client ID of the Managed Identity. Alternatively any +GUID-like value will also be interpreted as a user-assigned Managed Identity +client ID. + +To specify a Managed Identity associated with an Azure resource, you can use the +format resource://{resourceId} where {resourceId} is the ID of the resource. + +For more information about managed identities, see the Azure DevOps +documentation (https://learn.microsoft.com/en-us/azure/devops/integrate/get-started/authentication/service-principal-managed-identity). + +system: System-Assigned Managed Identity +[guid]: User-Assigned Managed Identity with the specified client ID +id://[guid]: User-Assigned Managed Identity with the specified client ID +resource://[guid]: User-Assigned Managed Identity for the associated resource + +Also see: GCM_AZREPOS_MANAGEDIDENTITY (environment.md#GCM_AZREPOS_MANAGEDIDENTITY) + +Corresponds to git config key: credential.azreposManagedIdentity + Azrepos Service Principal + Specify the client and tenant IDs of a service principal (https://docs.microsoft.com/en-us/azure/active-directory/develop/app-objects-and-service-principals) +to use when performing Microsoft authentication for Azure Repos. + +The value of this setting should be in the format: {tenantId}/{clientId}. + +You must also set at least one authentication mechanism if you set this value: + +- credential.azreposServicePrincipalSecret (#credentialazreposserviceprincipalsecret) +- credential.azreposServicePrincipalCertificateThumbprint (#credentialazreposserviceprincipalcertificatethumbprint) +- credential.azreposServicePrincipalCertificateSendX5C (#credentialazreposserviceprincipalcertificatesendx5c) + +For more information about service principals, see the Azure DevOps +documentation (https://learn.microsoft.com/en-us/azure/devops/integrate/get-started/authentication/service-principal-managed-identity). + +Corresponds to git config key: credential.azreposServicePrincipal + Azrepos Service Principal Secret + Specifies the client secret for the service principal (https://docs.microsoft.com/en-us/azure/active-directory/develop/app-objects-and-service-principals) when +performing Microsoft authentication for Azure Repos with +credential.azreposServicePrincipalSecret (#credentialazreposserviceprincipal) set. + +Corresponds to git config key: credential.azreposServicePrincipalSecret + Azrepos Service Principal Certificate Thumbprint + Specifies the thumbprint of a certificate to use when authenticating as a +service principal (https://docs.microsoft.com/en-us/azure/active-directory/develop/app-objects-and-service-principals) for Azure Repos when +GCM_AZREPOS_SERVICE_PRINCIPAL (#credentialazreposserviceprincipal) is set. + +Corresponds to git config key: credential.azreposServicePrincipalCertificateThumbprint + Azrepos Service Principal Certificate Send X5C + When using a certificate for service principal (https://docs.microsoft.com/en-us/azure/active-directory/develop/app-objects-and-service-principals) authentication, this configuration +specifies whether the X5C claim should be should be sent to the STS. Sending the x5c +enables application developers to achieve easy certificate rollover in Azure AD: +this method will send the public certificate to Azure AD along with the token request, +so that Azure AD can use it to validate the subject name based on a trusted issuer +policy. This saves the application admin from the need to explicitly manage the +certificate rollover. For details see https://aka.ms/msal-net-sni (https://aka.ms/msal-net-sni). + +Corresponds to git config key: credential.azreposServicePrincipalCertificateSendX5C + Normal Target + Turns on Trace2 Normal Format tracing - see Git's Trace2 Normal Format +documentation (https://git-scm.com/docs/api-trace2#_the_normal_format_target) for more details. + +Corresponds to git config key: trace2.normalTarget + Event Target + Turns on Trace2 Event Format tracing - see Git's Trace2 Event Format +documentation (https://git-scm.com/docs/api-trace2#_the_event_format_target) for more details. + +Corresponds to git config key: trace2.eventTarget + Perf Target + Turns on Trace2 Performance Format tracing - see Git's Trace2 Performance +Format documentation (https://git-scm.com/docs/api-trace2#_the_performance_format_target) for more details. + +Corresponds to git config key: trace2.perfTarget + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Provider: + + + Authority: + + + + + + + + + + + + + + + + + + + + + + + Allow Windows Auth: + + + + + + + + + + + + + Bitbucket Always Refresh Credentials: + + + Bitbucket Validate Stored Credentials: + + + + + + + + + + + + + GitHub Account Filtering: + + + + + + + + + + + + + + + + + + Credential Store: + + + + + + + + + + + + + + + + + + + + + + + Msauth Flow: + + + Msauth Use Broker: + + + Msauth Use Default Account: + + + Use Http Path: + + + Azrepos Credential Type: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/windows/policy-templates/generate-admx.ps1 b/src/windows/policy-templates/generate-admx.ps1 new file mode 100644 index 000000000..d1f8920e3 --- /dev/null +++ b/src/windows/policy-templates/generate-admx.ps1 @@ -0,0 +1,347 @@ +<# +.SYNOPSIS + Generates Windows Group Policy ADMX/ADML templates for Git Credential Manager. + +.DESCRIPTION + Parses docs/configuration.md to extract all GCM configuration settings and + generates GitCredentialManager.admx and en-US/GitCredentialManager.adml in + the same directory as this script. + +.EXAMPLE + ./generate-admx.ps1 + +.EXAMPLE + ./generate-admx.ps1 -ConfigurationMd ../../../docs/configuration.md +#> + +param( + [string]$ConfigurationMd = (Join-Path $PSScriptRoot '../../../docs/configuration.md'), + [string]$OutputDir = $PSScriptRoot +) + +$ErrorActionPreference = 'Stop' +Set-StrictMode -Version Latest + +$REGISTRY_KEY = 'SOFTWARE\GitCredentialManager\Configuration' +$GP_NS = 'http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions' +$XSD_NS = 'http://www.w3.org/2001/XMLSchema' +$XSI_NS = 'http://www.w3.org/2001/XMLSchema-instance' +$XMLNS_NS = 'http://www.w3.org/2000/xmlns/' + +$categories = @( + [ordered]@{ Name = 'GitCredentialManager'; Display = 'Git Credential Manager'; Parent = $null; Pattern = $null } + [ordered]@{ Name = 'GCM_Trace2'; Display = 'Trace2'; Parent = 'GitCredentialManager'; Pattern = '^trace2\.' } + [ordered]@{ Name = 'GCM_Tracing'; Display = 'Tracing'; Parent = 'GitCredentialManager'; Pattern = '\.trace' } + [ordered]@{ Name = 'GCM_Credentials'; Display = 'Credential Storage'; Parent = 'GitCredentialManager'; Pattern = 'Store(Path)?$|\.cacheOptions$' } + [ordered]@{ Name = 'GCM_Authentication'; Display = 'Authentication'; Parent = 'GitCredentialManager'; Pattern = '\.msauth' } + [ordered]@{ Name = 'GCM_AzureRepos'; Display = 'Azure Repos'; Parent = 'GitCredentialManager'; Pattern = '\.azrepos' } + [ordered]@{ Name = 'GCM_GitHub'; Display = 'GitHub'; Parent = 'GitCredentialManager'; Pattern = '\.github' } + [ordered]@{ Name = 'GCM_Bitbucket'; Display = 'Bitbucket'; Parent = 'GitCredentialManager'; Pattern = '\.bitbucket' } + [ordered]@{ Name = 'GCM_GitLab'; Display = 'GitLab'; Parent = 'GitCredentialManager'; Pattern = '\.gitlab' } + [ordered]@{ Name = 'GCM_General'; Display = 'General'; Parent = 'GitCredentialManager'; Pattern = $null } +) + +function New-XmlWriter { + param([string]$Path) + $xs = [System.Xml.XmlWriterSettings]::new() + $xs.Indent = $true + $xs.IndentChars = ' ' + $xs.Encoding = [System.Text.UTF8Encoding]::new($false) + $xs.NewLineHandling = [System.Xml.NewLineHandling]::Replace + return [System.Xml.XmlWriter]::Create($Path, $xs) +} + +function Write-AdmlString { + param($Writer, [string]$Id, [string]$Value) + $Writer.WriteStartElement('string') + $Writer.WriteAttributeString('id', $Id) + $Writer.WriteString($Value) + $Writer.WriteEndElement() +} + +$content = Get-Content -LiteralPath $ConfigurationMd -Raw +$settings = [System.Collections.Generic.List[hashtable]]::new() + +# Build a map of link-reference -> URL from the document footer +$linkDefs = @{} +foreach ($ld in [regex]::Matches($content, '(?m)^\[([^\]]+)\]:\s*(\S+)')) { + $linkDefs[$ld.Groups[1].Value.ToLower()] = $ld.Groups[2].Value +} + +# Match any namespace.setting heading plus the description paragraph that +# immediately follows it (up to the first subheading, horizontal rule, or EOF). +$pattern = '(?ms)^### ((\w+)\.(\S+?))(?:\s+_\([^)]+\)_)* *\n\n(.*?)(?=\n####|\n---|\Z)' +foreach ($m in [regex]::Matches($content, $pattern)) { + $fullKey = $m.Groups[1].Value + $namespace = $m.Groups[2].Value + $valueName = $m.Groups[3].Value + + $rawDesc = $m.Groups[4].Value + $plain = $rawDesc + + # Check if this setting supports multiple comma-separated values + $multiValue = $rawDesc -match 'multiple values separated by commas' + + # Extract enum options from a markdown table if present and not multi-value + $enumOptions = $null + if (-not $multiValue) { + $optRows = [System.Collections.Generic.List[hashtable]]::new() + foreach ($row in [regex]::Matches($rawDesc, '(?m)^\s*`([^`]+)`[^|\n]*\|([^|\n]+)')) { + $val = $row.Groups[1].Value + # Skip placeholder/template values (e.g. [guid], id://[guid]) + if ($val -match '[\[\{]|//') { continue } + # Strip markdown from the description column + $desc = $row.Groups[2].Value.Trim() ` + -replace '`([^`]+)`', '$1' ` + -replace '\*\*(.+?)\*\*', '$1' ` + -replace '(?]+>', '' + $optRows.Add(@{ Value = $val; Id = ($val -replace '[^A-Za-z0-9]', '_'); Display = "$val - $($desc.Trim())" }) + } + if ($optRows.Count -ge 2) { $enumOptions = $optRows.ToArray() } + } + + # Strip fenced code blocks + $plain = $plain -replace '(?ms)```[^`]*?```', '' + + # Strip table header rows (plain word|word lines with no backticks) before pipe processing + $plain = $plain -replace '(?m)^[A-Za-z][\w ]*(\|[\w ]+)+\s*$', '' + + # Strip inline code markers, keeping the text + $plain = $plain -replace '`([^`]+)`', '$1' + + # Resolve reference-style links [text][ref]: include URL/path for all known links + foreach ($ld in $linkDefs.GetEnumerator()) { + $escaped = [regex]::Escape($ld.Key) + $plain = $plain -replace "\[([^\]]+)\]\[$escaped\]", "`$1 ($($ld.Value))" + } + $plain = $plain -replace '\[([^\]]+)\]\[[^\]]*\]', '$1' + + # Resolve inline links [text](url): keep HTTP URLs, drop relative ones + $plain = [regex]::Replace($plain, '\[([^\]]+)\]\(([^\)]*)\)', { + param($match) + $text = $match.Groups[1].Value + $url = $match.Groups[2].Value + if ($url -match '^https?://') { return "$text ($url)" } + return $text + }) + + # Preserve bare autolinks + $plain = $plain -replace '<(https?://[^>]+)>', '$1' + + $plain = $plain ` + -replace '\\\[', '[' ` + -replace '\\\]', ']' ` + -replace '\*\*(.+?)\*\*', '$1' ` + -replace '(? ?', '' ` + -replace '(?m)^[\-|: ]+$', '' ` + -replace '\|', ': ' + $plain = ($plain -split '\r?\n' | ForEach-Object { $_.TrimEnd() }) -join "`n" + $plain = [regex]::Replace($plain, '\n{3,}', "`n`n").Trim() + + $deprecated = $m.Value -match '_\(deprecated\)_' + $explainText = if ($plain) { "$plain`n`nCorresponds to git config key: $fullKey" } + else { "Corresponds to git config key: $fullKey" } + if ($deprecated) { $explainText = "DEPRECATED. $explainText" } + + $policyName = if ($namespace -eq 'trace2') { + "GCM_trace2_$($valueName -replace '[^A-Za-z0-9]', '_')" + } else { + "GCM_$($valueName -replace '[^A-Za-z0-9]', '_')" + } + + # Split camelCase on lowercase-to-uppercase boundaries only (not digit-to-uppercase) + $displayName = [regex]::Replace($valueName, '(?<=[a-z])(?=[A-Z])', ' ') + $displayName = $displayName.Substring(0,1).ToUpper() + $displayName.Substring(1) + # Preserve known compound brand names that camelCase splitting would break + $displayName = $displayName -replace '\bGit Hub\b', 'GitHub' -replace '\bGit Lab\b', 'GitLab' + + $matched = $categories | Where-Object { $_.Pattern -and $fullKey -match $_.Pattern } | Select-Object -First 1 + $category = if ($matched) { $matched.Name } else { 'GCM_General' } + + $settings.Add(@{ + PolicyName = $policyName + ValueName = $fullKey + Category = $category + DisplayName = $displayName + Explain = $explainText + EnumOptions = $enumOptions + }) +} + +Write-Host "Parsed $($settings.Count) settings from $(Split-Path $ConfigurationMd -Leaf)" + +$admxPath = Join-Path $OutputDir 'GitCredentialManager.admx' +$xw = New-XmlWriter $admxPath + +$xw.WriteStartDocument() +$xw.WriteStartElement('policyDefinitions', $GP_NS) +$xw.WriteAttributeString('xmlns', 'xsd', $XMLNS_NS, $XSD_NS) +$xw.WriteAttributeString('xmlns', 'xsi', $XMLNS_NS, $XSI_NS) +$xw.WriteAttributeString('revision', '1.0') +$xw.WriteAttributeString('schemaVersion', '1.0') + +$xw.WriteStartElement('policyNamespaces') +$xw.WriteStartElement('target') +$xw.WriteAttributeString('prefix', 'GCM') +$xw.WriteAttributeString('namespace', 'Git.Policies.GitCredentialManager') +$xw.WriteEndElement() +$xw.WriteStartElement('using') +$xw.WriteAttributeString('prefix', 'windows') +$xw.WriteAttributeString('namespace', 'Microsoft.Policies.Windows') +$xw.WriteEndElement() +$xw.WriteEndElement() + +$xw.WriteStartElement('supersededAdm') +$xw.WriteAttributeString('fileName', '') +$xw.WriteEndElement() +$xw.WriteStartElement('resources') +$xw.WriteAttributeString('minRequiredRevision', '1.0') +$xw.WriteEndElement() + +$xw.WriteStartElement('supportedOn') +$xw.WriteStartElement('definitions') +$xw.WriteStartElement('definition') +$xw.WriteAttributeString('name', 'SUPPORTED_GCM') +$xw.WriteAttributeString('displayName', '$(string.SUPPORTED_GCM)') +$xw.WriteEndElement() +$xw.WriteEndElement() +$xw.WriteEndElement() + +$xw.WriteStartElement('categories') +foreach ($cat in $categories) { + $xw.WriteStartElement('category') + $xw.WriteAttributeString('name', $cat.Name) + $xw.WriteAttributeString('displayName', "`$(string.Cat_$($cat.Name))") + if ($cat.Parent) { + $xw.WriteStartElement('parentCategory') + $xw.WriteAttributeString('ref', $cat.Parent) + $xw.WriteEndElement() + } + $xw.WriteEndElement() +} +$xw.WriteEndElement() + +$xw.WriteStartElement('policies') +foreach ($s in $settings) { + $xw.WriteStartElement('policy') + $xw.WriteAttributeString('name', $s.PolicyName) + $xw.WriteAttributeString('class', 'Machine') + $xw.WriteAttributeString('displayName', "`$(string.$($s.PolicyName))") + $xw.WriteAttributeString('explainText', "`$(string.$($s.PolicyName)_Explain)") + $xw.WriteAttributeString('presentation', "`$(presentation.$($s.PolicyName))") + $xw.WriteAttributeString('key', $REGISTRY_KEY) + $xw.WriteAttributeString('valueName', $s.ValueName) + + $xw.WriteStartElement('parentCategory') + $xw.WriteAttributeString('ref', $s.Category) + $xw.WriteEndElement() + + $xw.WriteStartElement('supportedOn') + $xw.WriteAttributeString('ref', 'SUPPORTED_GCM') + $xw.WriteEndElement() + + $xw.WriteStartElement('elements') + if ($s.EnumOptions) { + $xw.WriteStartElement('enum') + $xw.WriteAttributeString('id', "$($s.PolicyName)_Enum") + $xw.WriteAttributeString('valueName', $s.ValueName) + foreach ($opt in $s.EnumOptions) { + $xw.WriteStartElement('item') + $xw.WriteAttributeString('displayName', "`$(string.$($s.PolicyName)_Enum_$($opt.Id))") + $xw.WriteStartElement('value') + $xw.WriteStartElement('string') + $xw.WriteString($opt.Value) + $xw.WriteEndElement() + $xw.WriteEndElement() + $xw.WriteEndElement() + } + $xw.WriteEndElement() + } else { + $xw.WriteStartElement('text') + $xw.WriteAttributeString('id', "$($s.PolicyName)_Text") + $xw.WriteAttributeString('valueName', $s.ValueName) + $xw.WriteEndElement() + } + $xw.WriteEndElement() + + $xw.WriteEndElement() +} +$xw.WriteEndElement() + +$xw.WriteEndElement() +$xw.WriteEndDocument() +$xw.Flush() +$xw.Close() + +Write-Host "Written: $admxPath" + +$enUsDir = Join-Path $OutputDir 'en-US' +if (-not (Test-Path $enUsDir)) { New-Item -ItemType Directory -Path $enUsDir | Out-Null } +$admlPath = Join-Path $enUsDir 'GitCredentialManager.adml' + +$xw = New-XmlWriter $admlPath + +$xw.WriteStartDocument() +$xw.WriteStartElement('policyDefinitionResources', $GP_NS) +$xw.WriteAttributeString('xmlns', 'xsd', $XMLNS_NS, $XSD_NS) +$xw.WriteAttributeString('xmlns', 'xsi', $XMLNS_NS, $XSI_NS) +$xw.WriteAttributeString('revision', '1.0') +$xw.WriteAttributeString('schemaVersion', '1.0') + +$xw.WriteElementString('displayName', 'Git Credential Manager Policy Settings') +$xw.WriteElementString('description', 'Group Policy settings for Git Credential Manager.') + +$xw.WriteStartElement('resources') +$xw.WriteStartElement('stringTable') + +Write-AdmlString $xw 'SUPPORTED_GCM' 'Git Credential Manager (any version)' +foreach ($cat in $categories) { + Write-AdmlString $xw "Cat_$($cat.Name)" $cat.Display +} +foreach ($s in $settings) { + Write-AdmlString $xw $s.PolicyName $s.DisplayName + Write-AdmlString $xw "$($s.PolicyName)_Explain" $s.Explain + if ($s.EnumOptions) { + foreach ($opt in $s.EnumOptions) { + Write-AdmlString $xw "$($s.PolicyName)_Enum_$($opt.Id)" $opt.Display + } + } +} + +$xw.WriteEndElement() # stringTable + +$xw.WriteStartElement('presentationTable') +foreach ($s in $settings) { + $xw.WriteStartElement('presentation') + $xw.WriteAttributeString('id', $s.PolicyName) + if ($s.EnumOptions) { + $xw.WriteStartElement('dropdownList') + $xw.WriteAttributeString('refId', "$($s.PolicyName)_Enum") + $xw.WriteAttributeString('noSort', 'true') + $xw.WriteString("$($s.DisplayName):") + $xw.WriteEndElement() + } else { + $xw.WriteStartElement('textBox') + $xw.WriteAttributeString('refId', "$($s.PolicyName)_Text") + $xw.WriteElementString('label', "$($s.DisplayName):") + $xw.WriteEndElement() + } + $xw.WriteEndElement() +} +$xw.WriteEndElement() # presentationTable + +$xw.WriteEndElement() # resources +$xw.WriteEndElement() # policyDefinitionResources +$xw.WriteEndDocument() +$xw.Flush() +$xw.Close() + +Write-Host "Written: $admlPath" +Write-Host "Done. Generated $($settings.Count) policy settings."