├── .gitignore ├── .vscode └── settings.json ├── Docs ├── BetterTls.md ├── Disable-Tls.md ├── Enable-Tls.md ├── Get-Tls.md └── Set-Tls.md ├── LICENSE ├── README.md ├── Tests ├── Help.Tests.ps1 ├── PSScriptAnalyzer.Tests.ps1 └── Public │ ├── Disable-Tls.Tests.ps1 │ ├── Enable-Tls.Tests.ps1 │ ├── Get-Tls.Tests.ps1 │ └── Set-Tls.Tests.ps1 ├── appveyor.yml ├── build.ps1 ├── deploy.PSDeploy.ps1 ├── psake.ps1 └── src └── BetterTls ├── BetterTls.psd1 ├── BetterTls.psm1 ├── Private ├── Clear-TlsOptionCache.ps1 └── Get-TlsOptionCache.ps1 └── Public ├── Disable-Tls.ps1 ├── Enable-Tls.ps1 ├── Get-Tls.ps1 └── Set-Tls.ps1 /.gitignore: -------------------------------------------------------------------------------- 1 | bin/* 2 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.words": [ 3 | "bnot", 4 | "wildcards" 5 | ], 6 | "powershell.codeFormatting.alignPropertyValuePairs": true, 7 | "powershell.codeFormatting.ignoreOneLineBlock": true, 8 | "powershell.codeFormatting.newLineAfterCloseBrace": true, 9 | "powershell.codeFormatting.newLineAfterOpenBrace": true, 10 | "powershell.codeFormatting.openBraceOnSameLine": true, 11 | "powershell.codeFormatting.preset": "OTBS", 12 | "powershell.codeFormatting.whitespaceAfterSeparator": true, 13 | "powershell.codeFormatting.whitespaceAroundOperator": true, 14 | "powershell.codeFormatting.whitespaceBeforeOpenBrace": true, 15 | "powershell.codeFormatting.whitespaceBeforeOpenParen": true, 16 | "editor.tabSize": 4, 17 | "editor.insertSpaces": true, 18 | "editor.renderWhitespace": "all", 19 | "editor.trimAutoWhitespace": true, 20 | "files.trimTrailingWhitespace": true, 21 | "editor.formatOnPaste": true, 22 | "editor.formatOnSave": true, 23 | "editor.formatOnType": true 24 | } -------------------------------------------------------------------------------- /Docs/BetterTls.md: -------------------------------------------------------------------------------- 1 | --- 2 | Module Name: BetterTls 3 | Module Guid: db2a59b5-d629-43ae-a8a8-cc34766aa00e 4 | Download Help Link: {{Please enter FwLink manually}} 5 | Help Version: {{Please enter version of help manually (X.X.X.X) format}} 6 | Locale: en-US 7 | --- 8 | 9 | # BetterTls Module 10 | ## Description 11 | A Module for best practice enabling and disabling of TLS protocols in Windows PowerShell 5.1 and older. 12 | 13 | ## BetterTls Cmdlets 14 | ### [Disable-Tls](Disable-Tls.md) 15 | Disables one or more supplied TLS versions without affecting other settings. 16 | 17 | ### [Enable-Tls](Enable-Tls.md) 18 | Enables one or more supplied TLS versions without affecting other settings. 19 | 20 | ### [Get-Tls](Get-Tls.md) 21 | Gets the current TLS configuration. 22 | 23 | ### [Set-Tls](Set-Tls.md) 24 | Sets the TLS settings with only those supplied. 25 | 26 | -------------------------------------------------------------------------------- /Docs/Disable-Tls.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: BetterTls-help.xml 3 | Module Name: BetterTls 4 | online version: 5 | schema: 2.0.0 6 | --- 7 | 8 | # Disable-Tls 9 | 10 | ## SYNOPSIS 11 | 12 | Disables one or more supplied TLS versions without affecting other settings. 13 | 14 | ## SYNTAX 15 | 16 | ``` 17 | Disable-Tls [-Tls12] [-Tls11] [-Tls] [-Ssl3] [-PassThru] [-WhatIf] [-Confirm] [] 18 | ``` 19 | 20 | ## DESCRIPTION 21 | 22 | Disables one or more supplied TLS versions. 23 | Other versions will not be affected. 24 | For example, it `-Tls` is supplied and `Tls, Tls11` is currently configured, only `Tls` will be disabled. 25 | 26 | These TLS Settings are used by `Invoke-WebRequest` and `Invoke-RestMethod` when connecting to remote end points. 27 | These settings may also be used by other .NET APIs. 28 | Caution should be used when changing this as you may decrease your security settings 29 | or break access to previously working endpoints. 30 | 31 | ## EXAMPLES 32 | 33 | ### Example 1 34 | 35 | ```powershell 36 | # Disable TLS 1.0 37 | Disable-Tls -Tls 38 | ``` 39 | 40 | The above example will disabled TLS 1.0. 41 | 42 | ## PARAMETERS 43 | 44 | ### -PassThru 45 | 46 | By default, this cmdlet does not supply any output. 47 | Supplying `-PassThru` will cause the cmdlet to return the current TLS configuration. 48 | 49 | ```yaml 50 | Type: SwitchParameter 51 | Parameter Sets: (All) 52 | Aliases: 53 | 54 | Required: False 55 | Position: Named 56 | Default value: None 57 | Accept pipeline input: False 58 | Accept wildcard characters: False 59 | ``` 60 | 61 | ### -Ssl3 62 | 63 | If supplied, SSL 3.0 will be disabled. 64 | 65 | ```yaml 66 | Type: SwitchParameter 67 | Parameter Sets: (All) 68 | Aliases: 69 | 70 | Required: False 71 | Position: Named 72 | Default value: None 73 | Accept pipeline input: False 74 | Accept wildcard characters: False 75 | ``` 76 | 77 | ### -Tls 78 | 79 | If supplied, TLS 1.0 will be disabled. 80 | 81 | ```yaml 82 | Type: SwitchParameter 83 | Parameter Sets: (All) 84 | Aliases: 85 | 86 | Required: False 87 | Position: Named 88 | Default value: None 89 | Accept pipeline input: False 90 | Accept wildcard characters: False 91 | ``` 92 | 93 | ### -Tls11 94 | 95 | If supplied, TLS 1.1 will be disabled. 96 | 97 | ```yaml 98 | Type: SwitchParameter 99 | Parameter Sets: (All) 100 | Aliases: 101 | 102 | Required: False 103 | Position: Named 104 | Default value: None 105 | Accept pipeline input: False 106 | Accept wildcard characters: False 107 | ``` 108 | 109 | ### -Tls12 110 | 111 | If supplied, TLS 1.2 will be disabled. 112 | 113 | ```yaml 114 | Type: SwitchParameter 115 | Parameter Sets: (All) 116 | Aliases: 117 | 118 | Required: False 119 | Position: Named 120 | Default value: None 121 | Accept pipeline input: False 122 | Accept wildcard characters: False 123 | ``` 124 | 125 | ### -Confirm 126 | 127 | Prompts you for confirmation before running the cmdlet. 128 | 129 | ```yaml 130 | Type: SwitchParameter 131 | Parameter Sets: (All) 132 | Aliases: cf 133 | 134 | Required: False 135 | Position: Named 136 | Default value: None 137 | Accept pipeline input: False 138 | Accept wildcard characters: False 139 | ``` 140 | 141 | ### -WhatIf 142 | 143 | Shows what would happen if the cmdlet runs. 144 | The cmdlet is not run. 145 | 146 | ```yaml 147 | Type: SwitchParameter 148 | Parameter Sets: (All) 149 | Aliases: wi 150 | 151 | Required: False 152 | Position: Named 153 | Default value: None 154 | Accept pipeline input: False 155 | Accept wildcard characters: False 156 | ``` 157 | 158 | ### CommonParameters 159 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). 160 | 161 | ## INPUTS 162 | 163 | ### None 164 | 165 | ## OUTPUTS 166 | 167 | ### System.Net.SecurityProtocolType 168 | 169 | ## NOTES 170 | 171 | This function calls `Set-Tls`. 172 | 173 | ## RELATED LINKS 174 | 175 | [https://github.com/markekraus/BetterTls/blob/master/Docs/Disable-Tls.md](https://github.com/markekraus/BetterTls/blob/master/Docs/Disable-Tls.md) 176 | [Enable-Tls](https://github.com/markekraus/BetterTls/blob/master/Docs/Enable-Tls.md) 177 | [Get-Tls](https://github.com/markekraus/BetterTls/blob/master/Docs/Get-Tls.md) 178 | [Set-Tls](https://github.com/markekraus/BetterTls/blob/master/Docs/Set-Tls.md) 179 | -------------------------------------------------------------------------------- /Docs/Enable-Tls.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: BetterTls-help.xml 3 | Module Name: BetterTls 4 | online version: 5 | schema: 2.0.0 6 | --- 7 | 8 | # Enable-Tls 9 | 10 | ## SYNOPSIS 11 | 12 | Enables one or more supplied TLS versions without affecting other settings. 13 | 14 | ## SYNTAX 15 | 16 | ``` 17 | Enable-Tls [-Tls12] [-Tls11] [-Tls] [-Ssl3] [-PassThru] [-WhatIf] [-Confirm] [] 18 | ``` 19 | 20 | ## DESCRIPTION 21 | 22 | Enables one or more supplied TLS versions. 23 | Other versions will not be affected. 24 | For example, it `-Tls` is supplied and `Tls11` is currently configured, the result will be `Tls, Tls11`. 25 | 26 | These TLS Settings are used by `Invoke-WebRequest` and `Invoke-RestMethod` when connecting to remote end points. 27 | These settings may also be used by other .NET APIs. 28 | Caution should be used when changing this as you may decrease your security settings 29 | or break access to previously working endpoints. 30 | 31 | ## EXAMPLES 32 | 33 | ### Example 1 34 | 35 | ```powershell 36 | # Enable TLS 1.2 37 | Enable-Tls -Tls12 38 | ``` 39 | 40 | The above example will enable TLS 1.2. 41 | 42 | ## PARAMETERS 43 | 44 | ### -PassThru 45 | 46 | By default, this cmdlet does not supply any output. 47 | Supplying `-PassThru` will cause the cmdlet to return the current TLS configuration. 48 | 49 | ```yaml 50 | Type: SwitchParameter 51 | Parameter Sets: (All) 52 | Aliases: 53 | 54 | Required: False 55 | Position: Named 56 | Default value: None 57 | Accept pipeline input: False 58 | Accept wildcard characters: False 59 | ``` 60 | 61 | ### -Ssl3 62 | 63 | If supplied, SSL 3.0 will be enabled. 64 | 65 | ```yaml 66 | Type: SwitchParameter 67 | Parameter Sets: (All) 68 | Aliases: 69 | 70 | Required: False 71 | Position: Named 72 | Default value: None 73 | Accept pipeline input: False 74 | Accept wildcard characters: False 75 | ``` 76 | 77 | ### -Tls 78 | 79 | If supplied, TLS 1.0 will be enabled. 80 | 81 | ```yaml 82 | Type: SwitchParameter 83 | Parameter Sets: (All) 84 | Aliases: 85 | 86 | Required: False 87 | Position: Named 88 | Default value: None 89 | Accept pipeline input: False 90 | Accept wildcard characters: False 91 | ``` 92 | 93 | ### -Tls11 94 | 95 | If supplied, TLS 1.1 will be enabled. 96 | 97 | ```yaml 98 | Type: SwitchParameter 99 | Parameter Sets: (All) 100 | Aliases: 101 | 102 | Required: False 103 | Position: Named 104 | Default value: None 105 | Accept pipeline input: False 106 | Accept wildcard characters: False 107 | ``` 108 | 109 | ### -Tls12 110 | 111 | If supplied, TLS 1.2 will be enabled. 112 | 113 | ```yaml 114 | Type: SwitchParameter 115 | Parameter Sets: (All) 116 | Aliases: 117 | 118 | Required: False 119 | Position: Named 120 | Default value: None 121 | Accept pipeline input: False 122 | Accept wildcard characters: False 123 | ``` 124 | 125 | ### -Confirm 126 | 127 | Prompts you for confirmation before running the cmdlet. 128 | 129 | ```yaml 130 | Type: SwitchParameter 131 | Parameter Sets: (All) 132 | Aliases: cf 133 | 134 | Required: False 135 | Position: Named 136 | Default value: None 137 | Accept pipeline input: False 138 | Accept wildcard characters: False 139 | ``` 140 | 141 | ### -WhatIf 142 | 143 | Shows what would happen if the cmdlet runs. 144 | The cmdlet is not run. 145 | 146 | ```yaml 147 | Type: SwitchParameter 148 | Parameter Sets: (All) 149 | Aliases: wi 150 | 151 | Required: False 152 | Position: Named 153 | Default value: None 154 | Accept pipeline input: False 155 | Accept wildcard characters: False 156 | ``` 157 | 158 | ### CommonParameters 159 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). 160 | 161 | ## INPUTS 162 | 163 | ### None 164 | 165 | ## OUTPUTS 166 | 167 | ### System.Net.SecurityProtocolType 168 | 169 | ## NOTES 170 | 171 | This function calls `Set-Tls`. 172 | 173 | ## RELATED LINKS 174 | 175 | [https://github.com/markekraus/BetterTls/blob/master/Docs/Enable-Tls.md](https://github.com/markekraus/BetterTls/blob/master/Docs/Enable-Tls.md) 176 | [Disable-Tls](https://github.com/markekraus/BetterTls/blob/master/Docs/Disable-Tls.md) 177 | [Get-Tls](https://github.com/markekraus/BetterTls/blob/master/Docs/Get-Tls.md) 178 | [Set-Tls](https://github.com/markekraus/BetterTls/blob/master/Docs/Set-Tls.md) 179 | -------------------------------------------------------------------------------- /Docs/Get-Tls.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: BetterTls-help.xml 3 | Module Name: BetterTls 4 | online version: 5 | schema: 2.0.0 6 | --- 7 | 8 | # Get-Tls 9 | 10 | ## SYNOPSIS 11 | 12 | Gets the current TLS configuration. 13 | 14 | ## SYNTAX 15 | 16 | ``` 17 | Get-Tls [] 18 | ``` 19 | 20 | ## DESCRIPTION 21 | 22 | Retrieves the current setting of `[System.Net.ServicePointManager]::SecurityProtocol`. 23 | 24 | These TLS Settings are used by `Invoke-WebRequest` and `Invoke-RestMethod` when connecting to remote end points. 25 | These settings may also be used by other .NET APIs. 26 | Caution should be used when changing this as you may decrease your security settings 27 | or break access to previously working endpoints. 28 | 29 | ## EXAMPLES 30 | 31 | ### Example 1 32 | 33 | ```powershell 34 | Get-Tls 35 | ``` 36 | 37 | Retrieve the current TLS settings. 38 | 39 | ## PARAMETERS 40 | 41 | ### CommonParameters 42 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). 43 | 44 | ## INPUTS 45 | 46 | ### None 47 | 48 | ## OUTPUTS 49 | 50 | ### System.Net.SecurityProtocolType 51 | 52 | ## NOTES 53 | 54 | ## RELATED LINKS 55 | 56 | [https://github.com/markekraus/BetterTls/blob/master/Docs/Get-Tls.md](https://github.com/markekraus/BetterTls/blob/master/Docs/Get-Tls.md) 57 | [Disable-Tls](https://github.com/markekraus/BetterTls/blob/master/Docs/Disable-Tls.md) 58 | [Enable-Tls](https://github.com/markekraus/BetterTls/blob/master/Docs/Enable-Tls.md) 59 | [Set-Tls](https://github.com/markekraus/BetterTls/blob/master/Docs/Set-Tls.md) 60 | -------------------------------------------------------------------------------- /Docs/Set-Tls.md: -------------------------------------------------------------------------------- 1 | --- 2 | external help file: BetterTls-help.xml 3 | Module Name: BetterTls 4 | online version: 5 | schema: 2.0.0 6 | --- 7 | 8 | # Set-Tls 9 | 10 | ## SYNOPSIS 11 | 12 | Sets the TLS settings with only those supplied. 13 | 14 | ## SYNTAX 15 | 16 | ### Switch (Default) 17 | ``` 18 | Set-Tls [-Tls12] [-Tls11] [-Tls] [-Ssl3] [-PassThru] [-Caller ] [-WhatIf] [-Confirm] 19 | [] 20 | ``` 21 | 22 | ### SecurityProtocol 23 | ``` 24 | Set-Tls -SecurityProtocol [-PassThru] [-Caller ] [-WhatIf] [-Confirm] 25 | [] 26 | ``` 27 | 28 | ## DESCRIPTION 29 | 30 | Sets the TLS settings with only those supplied. 31 | Settings not supplied will be disabled. 32 | For example, if `Ssl3, Tls` is currently set and `-Tls -Tls11 -Tls12` is supplied 33 | the result will be `Tls, Tls11, Tls12`. 34 | 35 | If the requested settings and the current settings are the same, no action will be taken. 36 | 37 | These TLS Settings are used by `Invoke-WebRequest` and `Invoke-RestMethod` when connecting to remote end points. 38 | These settings may also be used by other .NET APIs. 39 | Caution should be used when changing this as you may decrease your security settings 40 | or break access to previously working endpoints. 41 | 42 | ## EXAMPLES 43 | 44 | ### Example 1 45 | 46 | ```powershell 47 | Set-Tls -Tls -Tls11 -Tls12 48 | ``` 49 | 50 | This example enables TLS 1.0, 1.1, and 1.2 and disables all other settings. 51 | 52 | ### Example 2 53 | 54 | ```powershell 55 | $Setting = [System.Net.SecurityProtocolType]'Tls11, Tls12' 56 | Set-Tls -SecurityProtocol $Setting 57 | ``` 58 | 59 | This example enables TLS 1.1, and 1.2 and disables all other settings. 60 | 61 | ## PARAMETERS 62 | 63 | ### -Caller 64 | 65 | This parameter is for internal use only. 66 | 67 | ```yaml 68 | Type: PSCmdlet 69 | Parameter Sets: (All) 70 | Aliases: 71 | 72 | Required: False 73 | Position: Named 74 | Default value: None 75 | Accept pipeline input: False 76 | Accept wildcard characters: False 77 | ``` 78 | 79 | ### -PassThru 80 | 81 | By default, this cmdlet does not supply any output. 82 | Supplying `-PassThru` will cause the cmdlet to return the current TLS configuration. 83 | 84 | ```yaml 85 | Type: SwitchParameter 86 | Parameter Sets: (All) 87 | Aliases: 88 | 89 | Required: False 90 | Position: Named 91 | Default value: None 92 | Accept pipeline input: False 93 | Accept wildcard characters: False 94 | ``` 95 | 96 | ### -SecurityProtocol 97 | 98 | A `System.Net.SecurityProtocolType` to overwrite the current TLS settings with. 99 | 100 | ```yaml 101 | Type: SecurityProtocolType 102 | Parameter Sets: SecurityProtocol 103 | Aliases: 104 | Accepted values: SystemDefault, Ssl3, Tls, Tls11, Tls12 105 | 106 | Required: True 107 | Position: Named 108 | Default value: None 109 | Accept pipeline input: False 110 | Accept wildcard characters: False 111 | ``` 112 | 113 | ### -Ssl3 114 | 115 | If supplied, SSL 3.0 will be enabled. 116 | If not supplied it will be disabled. 117 | If no other settings are supplied, only this setting will be applied. 118 | If other settings are supplied, this setting will be enabled along with the other settings. 119 | 120 | ```yaml 121 | Type: SwitchParameter 122 | Parameter Sets: Switch 123 | Aliases: 124 | 125 | Required: False 126 | Position: Named 127 | Default value: None 128 | Accept pipeline input: False 129 | Accept wildcard characters: False 130 | ``` 131 | 132 | ### -Tls 133 | 134 | If supplied, TLS 1.0 will be enabled. 135 | If not supplied it will be disabled. 136 | If no other settings are supplied, only this setting will be applied. 137 | If other settings are supplied, this setting will be enabled along with the other settings. 138 | 139 | ```yaml 140 | Type: SwitchParameter 141 | Parameter Sets: Switch 142 | Aliases: 143 | 144 | Required: False 145 | Position: Named 146 | Default value: None 147 | Accept pipeline input: False 148 | Accept wildcard characters: False 149 | ``` 150 | 151 | ### -Tls11 152 | 153 | If supplied, TLS 1.1 will be enabled. 154 | If not supplied it will be disabled. 155 | If no other settings are supplied, only this setting will be applied. 156 | If other settings are supplied, this setting will be enabled along with the other settings. 157 | 158 | ```yaml 159 | Type: SwitchParameter 160 | Parameter Sets: Switch 161 | Aliases: 162 | 163 | Required: False 164 | Position: Named 165 | Default value: None 166 | Accept pipeline input: False 167 | Accept wildcard characters: False 168 | ``` 169 | 170 | ### -Tls12 171 | 172 | If supplied, TLS 1.2 will be enabled. 173 | If not supplied it will be disabled. 174 | If no other settings are supplied, only this setting will be applied. 175 | If other settings are supplied, this setting will be enabled along with the other settings. 176 | 177 | ```yaml 178 | Type: SwitchParameter 179 | Parameter Sets: Switch 180 | Aliases: 181 | 182 | Required: False 183 | Position: Named 184 | Default value: None 185 | Accept pipeline input: False 186 | Accept wildcard characters: False 187 | ``` 188 | 189 | ### -Confirm 190 | 191 | Prompts you for confirmation before running the cmdlet. 192 | 193 | ```yaml 194 | Type: SwitchParameter 195 | Parameter Sets: (All) 196 | Aliases: cf 197 | 198 | Required: False 199 | Position: Named 200 | Default value: None 201 | Accept pipeline input: False 202 | Accept wildcard characters: False 203 | ``` 204 | 205 | ### -WhatIf 206 | 207 | Shows what would happen if the cmdlet runs. 208 | The cmdlet is not run. 209 | 210 | ```yaml 211 | Type: SwitchParameter 212 | Parameter Sets: (All) 213 | Aliases: wi 214 | 215 | Required: False 216 | Position: Named 217 | Default value: None 218 | Accept pipeline input: False 219 | Accept wildcard characters: False 220 | ``` 221 | 222 | ### CommonParameters 223 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). 224 | 225 | ## INPUTS 226 | 227 | ### None 228 | 229 | ## OUTPUTS 230 | 231 | ### System.Net.SecurityProtocolType 232 | 233 | ## NOTES 234 | 235 | This function is called by `Enable-Tls` and `Disable-Tls`. 236 | 237 | ## RELATED LINKS 238 | 239 | [https://github.com/markekraus/BetterTls/blob/master/Docs/Set-Tls.md](https://github.com/markekraus/BetterTls/blob/master/Docs/Set-Tls.md) 240 | [Disable-Tls](https://github.com/markekraus/BetterTls/blob/master/Docs/Disable-Tls.md) 241 | [Enable-Tls](https://github.com/markekraus/BetterTls/blob/master/Docs/Enable-Tls.md) 242 | [Get-Tls](https://github.com/markekraus/BetterTls/blob/master/Docs/Get-Tls.md) 243 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Mark Kraus 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BetterTls 2 | 3 | ## Module Information 4 | 5 | BetterTls is a PowerShell Module to manage TLS settings for `Invoke-WebRequest` and `Invoke-RestMethod` in Windows PowerShell 5.1 and older. 6 | 7 | In Windows PowerShell 5.1 and older, only SSL 3.0 and TLS 1.0 are enabled by default. 8 | Many modern APIs, including GitHub, have begun moving to support only TLS 1.2. 9 | If you attempt to use those APIs with `Invoke-WebRequest` and/or `Invoke-RestMethod` you will received the following error: 10 | 11 | ```none 12 | Invoke-RestMethod : The request was aborted: Could not create SSL/TLS secure channel. 13 | At line:1 char:1 14 | + Invoke-RestMethod https://api.github.com/repositories/49609581/issues ... 15 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 16 | + CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException 17 | + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand 18 | 19 | Invoke-WebRequest : The request was aborted: Could not create SSL/TLS secure channel. 20 | At line:1 char:1 21 | + Invoke-WebRequest https://api.github.com/repositories/49609581/issues ... 22 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 23 | + CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException 24 | + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand 25 | ``` 26 | 27 | This module provides best practice ways to enable and disable TLS protocols. 28 | Many module and script authors are setting these directly without prompting for user consent. 29 | That practice is dangerous as it may decrease the user's security or break access to previously working APIs. 30 | These settings affect .NET APIs beyond just `Invoke-WebRequest` and `Invoke-RestMethod`. 31 | Additionally, the settings persist for the duration of the user's PowerShell Session at the AppDomain level. 32 | These authors mean well, but may not fully understand all the implications of their actions. 33 | 34 | The functions in this module require user consent before making changes to the TLS settings, 35 | but only when settings are actually required. 36 | If the user's settings already include the code authors desired settings, 37 | then the user is not prompted and no changes are made. 38 | 39 | The confirmation prompts can be suppressed for automation jobs. 40 | However, when working with user facing and interactive code, the prompts should not be suppressed. 41 | This allows the user to be made aware of the changes being made to their session. 42 | 43 | PowerShell Core 6.0.0 and later do not require this module. 44 | `Invoke-WebRequest` and `Invoke-RestMethod` are not affected by settings made to `System.Net.ServicePointManager` in PowerShell Core. 45 | TLS 1.0, 1.1, and 1.2 are enabled by default in PowerShell Core. 46 | For more information on this and other differences please [see my blog](https://get-powershellblog.blogspot.com/2017/11/powershell-core-web-cmdlets-in-depth.html). 47 | 48 | ## Installation 49 | 50 | BetterTls is available on the [PowerShell Gallery](https://www.powershellgallery.com/packages/BetterTls/). To install to the following: 51 | 52 | ```powershell 53 | Install-Module -Scope CurrentUser -Name BetterTls 54 | ``` 55 | 56 | ## Including in Your Module 57 | 58 | To include BetterTls in your PowerShell Gallery module, add the following to your `.psd1` 59 | 60 | ```powershell 61 | RequiredModules = @('BetterTls') 62 | ``` 63 | 64 | To enable TLS 1.2 for your module code, include the following in your `.psm1`: 65 | 66 | ```powershell 67 | Enable-Tls -Tls12 68 | ``` 69 | 70 | That's it! 71 | The user will be prompted to enable TLS 1.2 upon module load. 72 | You can also include this before any code that accesses an endpoint that requires TLS 1.2. 73 | If the user already has TLS 1.2 enabled, they will not be prompted and no changes will be made. 74 | If the user has disabled TLS 1.2 since module load then they would be prompted again to enable it. 75 | 76 | ## Documentation 77 | 78 | You can find documentation [here](https://github.com/markekraus/BetterTls/blob/master/Docs/BetterTls.md) or by running the following in PowerShell: 79 | 80 | ```powershell 81 | Get-Help Enable-Tls 82 | Get-Help Disable-Tls 83 | Get-Help Set-Tls 84 | Get-Help Get-Tls 85 | ``` 86 | 87 | ## Support 88 | 89 | For support, please open an [issue](https://github.com/markekraus/BetterTls/issues/new). 90 | -------------------------------------------------------------------------------- /Tests/Help.Tests.ps1: -------------------------------------------------------------------------------- 1 | Describe "Help tests for $ENV:BHProjectName" -Tags Documentation { 2 | BeforeAll { 3 | $ModuleName = $ENV:BHProjectName 4 | $ProjectRoot = (Resolve-Path $ENV:BHProjectPath\..\).Path 5 | $ModulePath = "$ENV:BHBuildOutput\$ENV:BHProjectName.psd1" 6 | Import-Module $ModulePath -Force -Global 7 | $DocsFolder = Join-Path $ProjectRoot "Docs" 8 | $BaseURL = 'https://github.com/markekraus/BetterTls/tree/master/Docs' 9 | $functions = Get-Command -Module $ModuleName -CommandType Function 10 | $PublicHelpFiles = Get-ChildItem -Path $DocsFolder -Filter '*.md' -ErrorAction SilentlyContinue 11 | $DefaultParams = @( 12 | 'Verbose' 13 | 'Debug' 14 | 'ErrorAction' 15 | 'WarningAction' 16 | 'InformationAction' 17 | 'ErrorVariable' 18 | 'WarningVariable' 19 | 'InformationVariable' 20 | 'OutVariable' 21 | 'OutBuffer' 22 | 'PipelineVariable' 23 | 'WhatIf' 24 | 'Confirm' 25 | ) 26 | } 27 | # Public Functions 28 | foreach ($Function in $Functions) { 29 | $help = Get-Help $Function.name -Full -ErrorAction SilentlyContinue 30 | $helpText = $help | Out-String 31 | $helpDoc = $PublicHelpFiles | Where-Object { $_.BaseName -eq $Function.name} 32 | Context "$($Function.name) Public Function" { 33 | it "Has a Valid HelpUri" { 34 | $Function.HelpUri | Should Not BeNullOrEmpty 35 | $Pattern = [regex]::Escape("$ModuleBaseURL/$($Function.name)") 36 | $Function.HelpUri | should Match $Pattern 37 | } 38 | It "Has related Links" { 39 | $help.relatedLinks.navigationLink.uri.count | Should BeGreaterThan 0 40 | } 41 | it "Has a description" { 42 | $help.description | Should Not BeNullOrEmpty 43 | } 44 | it "Has an example" { 45 | $help.examples | Should Not BeNullOrEmpty 46 | } 47 | it "Does not have Template artifacts" { 48 | $helpDoc.FullName | should not Contain '{{.*}}' 49 | } 50 | foreach ($parameter in $help.parameters.parameter) { 51 | if ($parameter -notin $DefaultParams) { 52 | it "Has a Parameter description for '$($parameter.name)'" { 53 | $parameter.Description.text -join '' | Should Not BeNullOrEmpty 54 | } 55 | } 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Tests/PSScriptAnalyzer.Tests.ps1: -------------------------------------------------------------------------------- 1 | Describe "PSScriptAnalyzer Tests" -Tags Build { 2 | BeforeAll { 3 | $ModulePath = "$ENV:BHBuildOutput\$ENV:BHProjectName.psd1" 4 | $ModuleRoot = Resolve-Path (Split-Path -Parent $ModulePath) 5 | Import-Module $ModulePath 6 | $Params = @{ 7 | Path = $ModuleRoot 8 | Severity = @('Error', 'Warning') 9 | Recurse = $true 10 | Verbose = $false 11 | ErrorVariable = 'ErrorVariable' 12 | ErrorAction = 'SilentlyContinue' 13 | } 14 | $ScriptWarnings = Invoke-ScriptAnalyzer @Params 15 | $scripts = Get-ChildItem $ModuleRoot -Include *.ps1, *.psm1 -Recurse 16 | } 17 | 18 | foreach ($Script in $scripts) { 19 | $RelPath = $Script.FullName.Replace($ModuleRoot, '') -replace '^\\', '' 20 | 21 | Context "$RelPath" { 22 | $Rules = $ScriptWarnings | 23 | Where-Object {$_.ScriptPath -like $Script.FullName} | 24 | Select-Object -ExpandProperty RuleName -Unique 25 | 26 | foreach ($rule in $Rules) { 27 | It "Passes $rule" { 28 | $BadLines = $ScriptWarnings | 29 | Where-Object {$_.ScriptPath -like $Script.FullName -and $_.RuleName -like $rule} | 30 | Select-Object -ExpandProperty Line 31 | $BadLines | Should -BeNullOrEmpty 32 | } 33 | } 34 | 35 | $Exceptions = $ErrorVariable.Exception.Message | 36 | Where-Object {$_ -match [regex]::Escape($Script.FullName)} 37 | 38 | foreach ($Exception in $Exceptions) { 39 | it 'Has no parse errors' { 40 | $Exception | Should -BeNullOrEmpty 41 | } 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Tests/Public/Disable-Tls.Tests.ps1: -------------------------------------------------------------------------------- 1 | $ModulePath = "$ENV:BHBuildOutput\$ENV:BHProjectName.psd1" 2 | Import-Module $ModulePath -Force 3 | 4 | Describe 'Disable-Tls' -Tag 'Unit' { 5 | BeforeAll { 6 | $Original = [System.Net.ServicePointManager]::SecurityProtocol 7 | $OriginalPreference = $ConfirmPreference 8 | $Global:ConfirmPreference = 'None' 9 | } 10 | 11 | BeforeEach { 12 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]'Tls, Tls11, Tls12' 13 | } 14 | 15 | It "It Disables " -TestCases @( 16 | @{T = 'Tls'; params = @{Tls = $True}; Expected = [System.Net.SecurityProtocolType]'Tls11, Tls12' } 17 | @{T = 'Tls11'; params = @{Tls11 = $True}; Expected = [System.Net.SecurityProtocolType]'Tls, Tls12' } 18 | @{T = 'Tls12'; params = @{Tls12 = $True}; Expected = [System.Net.SecurityProtocolType]'Tls, Tls11' } 19 | @{T = 'Tls, Tls11'; params = @{Tls = $True; Tls11 = $True}; Expected = [System.Net.SecurityProtocolType]'Tls12' } 20 | @{T = 'Tls, Tls12'; params = @{Tls = $True; Tls12 = $True}; Expected = [System.Net.SecurityProtocolType]'Tls11' } 21 | @{T = 'Tls11, Tls12'; params = @{Tls11 = $True; Tls12 = $True}; Expected = [System.Net.SecurityProtocolType]'Tls' } 22 | @{T = 'Tls, Tls11, Tls12'; params = @{Tls = $True; Tls11 = $True; Tls12 = $True}; Expected = [System.Net.SecurityProtocolType]::SystemDefault } 23 | ) { 24 | Param($params, $Expected) 25 | Disable-Tls @params 26 | Get-Tls | Should -Be $Expected 27 | } 28 | 29 | It "Supports PassThru" { 30 | Disable-Tls -Tls -PassThru | Should -Be ([System.Net.SecurityProtocolType]'Tls11, Tls12') 31 | } 32 | 33 | It "Supports WhatIf" { 34 | $Before = Get-Tls 35 | Disable-Tls -Tls12 -WhatIf 36 | Get-Tls | Should -Be $Before 37 | } 38 | 39 | AfterAll { 40 | [System.Net.ServicePointManager]::SecurityProtocol = $Original 41 | $Global:ConfirmPreference = $OriginalPreference 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Tests/Public/Enable-Tls.Tests.ps1: -------------------------------------------------------------------------------- 1 | $ModulePath = "$ENV:BHBuildOutput\$ENV:BHProjectName.psd1" 2 | Import-Module $ModulePath -Force 3 | 4 | Describe 'Enable-Tls' -Tag 'Unit' { 5 | BeforeAll { 6 | $Original = [System.Net.ServicePointManager]::SecurityProtocol 7 | $OriginalPreference = $ConfirmPreference 8 | $Global:ConfirmPreference = 'None' 9 | } 10 | 11 | BeforeEach { 12 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::SystemDefault 13 | } 14 | 15 | It "It Enables " -TestCases @( 16 | @{params = @{Tls = $True}; Expected = [System.Net.SecurityProtocolType]'Tls' } 17 | @{params = @{Tls11 = $True}; Expected = [System.Net.SecurityProtocolType]'Tls11' } 18 | @{params = @{Tls12 = $True}; Expected = [System.Net.SecurityProtocolType]'Tls12' } 19 | @{params = @{Tls = $True; Tls11 = $True}; Expected = [System.Net.SecurityProtocolType]'Tls, Tls11' } 20 | @{params = @{Tls = $True; Tls12 = $True}; Expected = [System.Net.SecurityProtocolType]'Tls, Tls12' } 21 | @{params = @{Tls11 = $True; Tls12 = $True}; Expected = [System.Net.SecurityProtocolType]'Tls11, Tls12' } 22 | @{params = @{Tls = $True; Tls11 = $True; Tls12 = $True}; Expected = [System.Net.SecurityProtocolType]'Tls, Tls11, Tls12' } 23 | ) { 24 | Param($params, $Expected) 25 | Enable-Tls @params 26 | Get-Tls | Should -Be $Expected 27 | } 28 | 29 | It "Supports PassThru" { 30 | Enable-Tls -Tls12 -PassThru | Should -Be ([System.Net.SecurityProtocolType]'Tls12') 31 | } 32 | 33 | It "Supports WhatIf" { 34 | $Before = Get-Tls 35 | Enable-Tls -Tls12 -WhatIf 36 | Get-Tls | Should -Be $Before 37 | } 38 | 39 | AfterAll { 40 | [System.Net.ServicePointManager]::SecurityProtocol = $Original 41 | $Global:ConfirmPreference = $OriginalPreference 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Tests/Public/Get-Tls.Tests.ps1: -------------------------------------------------------------------------------- 1 | $ModulePath = "$ENV:BHBuildOutput\$ENV:BHProjectName.psd1" 2 | Import-Module $ModulePath -Force 3 | 4 | Describe "Get-Tls" -Tag 'Unit' { 5 | It "Retrieves the current TLS Settings" { 6 | Get-Tls | Should -Be ([System.Net.ServicePointManager]::SecurityProtocol) 7 | } 8 | } -------------------------------------------------------------------------------- /Tests/Public/Set-Tls.Tests.ps1: -------------------------------------------------------------------------------- 1 | $ModulePath = "$ENV:BHBuildOutput\$ENV:BHProjectName.psd1" 2 | Import-Module $ModulePath -Force 3 | 4 | Describe "Set-Tls" -Tag 'Unit' { 5 | BeforeAll { 6 | $Original = [System.Net.ServicePointManager]::SecurityProtocol 7 | $OriginalPreference = $ConfirmPreference 8 | $Global:ConfirmPreference = 'None' 9 | } 10 | 11 | BeforeEach { 12 | [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::SystemDefault 13 | } 14 | 15 | It "Sets TLS via switch " -TestCases @( 16 | @{params = @{Tls = $True}; Expected = [System.Net.SecurityProtocolType]'Tls' } 17 | @{params = @{Tls11 = $True}; Expected = [System.Net.SecurityProtocolType]'Tls11' } 18 | @{params = @{Tls12 = $True}; Expected = [System.Net.SecurityProtocolType]'Tls12' } 19 | @{params = @{Tls = $True; Tls11 = $True}; Expected = [System.Net.SecurityProtocolType]'Tls, Tls11' } 20 | @{params = @{Tls = $True; Tls12 = $True}; Expected = [System.Net.SecurityProtocolType]'Tls, Tls12' } 21 | @{params = @{Tls11 = $True; Tls12 = $True}; Expected = [System.Net.SecurityProtocolType]'Tls11, Tls12' } 22 | @{params = @{Tls = $True; Tls11 = $True; Tls12 = $True}; Expected = [System.Net.SecurityProtocolType]'Tls, Tls11, Tls12' } 23 | ) { 24 | Param($params, $Expected) 25 | Set-Tls @params 26 | Get-Tls | Should -Be $Expected 27 | } 28 | 29 | It "Supports PassThru for Switches" { 30 | Set-Tls -Tls12 -PassThru | Should -Be ([System.Net.SecurityProtocolType]'Tls12') 31 | } 32 | 33 | It "Supports Settings TLS via SecurityProtocolType " -TestCases @( 34 | @{Type = [System.Net.SecurityProtocolType]'Tls'} 35 | @{Type = [System.Net.SecurityProtocolType]'Tls11'} 36 | @{Type = [System.Net.SecurityProtocolType]'Tls12'} 37 | @{Type = [System.Net.SecurityProtocolType]'Tls, Tls11'} 38 | @{Type = [System.Net.SecurityProtocolType]'Tls, Tls12'} 39 | @{Type = [System.Net.SecurityProtocolType]'Tls11, Tls12'} 40 | @{Type = [System.Net.SecurityProtocolType]'Tls, Tls11, Tls12'} 41 | ) { 42 | param($Type) 43 | Set-Tls -SecurityProtocol $Type 44 | Get-Tls | Should -Be $Type 45 | } 46 | 47 | It "Does not Change the settings if they are already as requested" { 48 | $Before = Get-Tls 49 | Set-Tls -SecurityProtocol $Before 50 | Get-Tls | Should -Be $Before 51 | } 52 | 53 | It "Supports PassThru on SecurityProtocolType" { 54 | $Tls12 = [System.Net.SecurityProtocolType]'Tls12' 55 | Set-Tls -SecurityProtocol $Tls12 -PassThru | Should -Be $Tls12 56 | Get-Tls | Should -Be $Tls12 57 | } 58 | 59 | It "Supports WhatIf on Switches" { 60 | $Before = Get-Tls 61 | Set-Tls -Tls12 -WhatIf 62 | Get-Tls | Should -Be $Before 63 | } 64 | 65 | It "Supports WhatIf on SecurityProtocolType" { 66 | $Before = Get-Tls 67 | $Tls12 = [System.Net.SecurityProtocolType]'Tls12' 68 | Set-Tls -SecurityProtocol $Tls12 -WhatIf 69 | Get-Tls | Should -Be $Before 70 | } 71 | 72 | AfterAll { 73 | [System.Net.ServicePointManager]::SecurityProtocol = $Original 74 | $Global:ConfirmPreference = $OriginalPreference 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # See http://www.appveyor.com/docs/appveyor-yml for many more options 2 | version: 0.0.1.{build} 3 | skip_tags: true 4 | image: Visual Studio 2017 5 | environment: 6 | APPVEYOR_SAVE_CACHE_ON_ERROR: true 7 | NugetApiKey: 8 | secure: 3sC7bUSY534F4WnpYXlP7XyikulxbSpfLZgC3y37gA2OAeMp35la0zplVjiliOFn 9 | ModuleName: BetterTls 10 | 11 | build: false 12 | 13 | test_script: 14 | - ps: . .\build.ps1 15 | -------------------------------------------------------------------------------- /build.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .NOTES 3 | 4 | Created with: VSCode 5 | Created on: 4/23/2017 6 | Edited on: 4/23/2017 7 | Created by: Mark Kraus 8 | Organization: 9 | Filename: build.ps1 10 | 11 | .DESCRIPTION 12 | Build Initialization 13 | #> 14 | param ($Task = 'Default') 15 | 16 | Get-PackageProvider -Name NuGet -ForceBootstrap | Out-Null 17 | 18 | $PSDefaultParameterValues['Install-Module:Scope'] = 'CurrentUser' 19 | 20 | @( 21 | @{Name = 'Psake'; RequiredVersion = '4.7.0'} 22 | @{Name = 'Pester'; RequiredVersion = '4.3.1'; SkipPublisherCheck = $true} 23 | @{Name = 'PSDeploy'; RequiredVersion = '0.2.3'} 24 | @{Name = 'BuildHelpers'; RequiredVersion = '1.0.1'} 25 | @{Name = 'PSScriptAnalyzer'; RequiredVersion = '1.16.1'} 26 | @{Name = 'PlatyPS'; RequiredVersion = '0.9.0' } 27 | 28 | ) | Foreach-Object { 29 | $Params = $_ 30 | 'Proceesing Module {0} Version = {1}' -f $Params.Name, $Params.RequiredVersion 31 | if ($ENV:APPVEYOR) { 32 | Install-Module -Force @Params 33 | } 34 | Remove-Module -Force -Name $Params.Name -ErrorAction SilentlyContinue 35 | try {$Params.Remove('SkipPublisherCheck')}catch {} 36 | Import-Module -Global -Force @Params 37 | } 38 | 39 | Set-BuildEnvironment -ErrorAction SilentlyContinue 40 | Set-BuildEnvironment -ErrorAction SilentlyContinue -Path src -Force 41 | Set-BuildEnvironment -ErrorAction SilentlyContinue -Force 42 | $ENV:BHBuildOutput = Join-Path $ENV:BHProjectPath "bin\$ENV:BHProjectName" 43 | 44 | Invoke-psake -buildFile .\psake.ps1 -taskList $Task -nologo 45 | exit ([int](-not $psake.build_success)) 46 | -------------------------------------------------------------------------------- /deploy.PSDeploy.ps1: -------------------------------------------------------------------------------- 1 | if ($ENV:ModuleName -and $ENV:ModuleName.Count -eq 1) { 2 | Deploy Module { 3 | By PSGalleryModule { 4 | FromSource $ENV:BHBuildOutput 5 | To PSGallery 6 | WithOptions @{ 7 | ApiKey = $ENV:NugetApiKey 8 | } 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /psake.ps1: -------------------------------------------------------------------------------- 1 | # PSake makes variables declared here available in other scriptblocks 2 | # Init some things 3 | Properties { 4 | # Find the build folder based on build system 5 | $ProjectRoot = $ENV:BHProjectPath 6 | if (-not $ProjectRoot) { 7 | $ProjectRoot = $PSScriptRoot 8 | } 9 | $ModuleFolder = $ENV:BHModulePath 10 | $ModuleName = $ENV:BHProjectName 11 | $DestinationManifest = Join-Path $ENV:BHBuildOutput "$ModuleName.psd1" 12 | $SourceModuleRoot = Join-Path $ENV:BHModulePath "$ModuleName.psm1" 13 | $DestinationRootModule = Join-Path $ENV:BHBuildOutput "$ModuleName.psm1" 14 | $DestinationFolder = $ENV:BHBuildOutput 15 | If (-not $ModuleName) { 16 | $ModuleName = Split-Path -Path $ModuleFolder -Leaf 17 | } 18 | $PSVersion = $PSVersionTable.PSVersion.Major 19 | $TestFile = "TestResults_PS$PSVersion`_$TimeStamp.xml" 20 | $lines = '----------------------------------------------------------------------' 21 | $Verbose = @{ } 22 | if ($ENV:BHCommitMessage -match "!verbose") { 23 | $Verbose = @{ Verbose = $True } 24 | } 25 | $CurrentVersion = [version](Get-Metadata -Path $env:BHPSModuleManifest) 26 | $BuildVersion = [version]::New($CurrentVersion.Major, $CurrentVersion.Minor, $CurrentVersion.Build, ($CurrentVersion.Revision + 1)) 27 | if ($ENV:BHBranchName -eq "master") { 28 | $BuildVersion = [version]::New($CurrentVersion.Major, $CurrentVersion.Minor, ($CurrentVersion.Build + 1), 0) 29 | } 30 | If ($ENV:BHBranchName -eq "master" -and $ENV:BHCommitMessage -match '!deploy') { 31 | $GalleryVersion = Get-NextPSGalleryVersion -Name $ModuleName 32 | $BuildVersion = [version]::New($CurrentVersion.Major, ($CurrentVersion.Minor + 1), 0, 0) 33 | if ( 34 | $CurrentVersion.Minor -eq 0 -and 35 | $CurrentVersion.Build -eq 0 -and 36 | $CurrentVersion.Revision -eq 0 37 | ) { 38 | #This is a major version release, don't molest the the version 39 | $BuildVersion = $CurrentVersion 40 | } 41 | If ($GalleryVersion -gt $BuildVersion) { 42 | $BuildVersion = $GalleryVersion 43 | } 44 | } 45 | $BuildDate = Get-Date -uFormat '%Y-%m-%d' 46 | $CodeCoverageExclude = @() 47 | $DocsFolder = Join-Path $ProjectRoot "Docs" 48 | $TestsFolder = Join-Path $ProjectRoot "Tests" 49 | } 50 | 51 | Task Default -Depends Init, Build, Test, BuildDocs, TestDocs, Deploy 52 | 53 | Task Init { 54 | $lines 55 | Set-Location $ProjectRoot 56 | "Build System Details:" 57 | Get-Item ENV:BH* | Format-Table -aut | Out-String 58 | "Current Version: $CurrentVersion`n" 59 | "Build Version: $BuildVersion`n" 60 | } 61 | 62 | Task Build -Depends Init { 63 | $lines 64 | New-Item -ItemType Directory -Path $DestinationFolder -Force -ErrorAction SilentlyContinue 65 | Copy-Item $ENV:BHPSModuleManifest $DestinationManifest -Force 66 | 67 | # Bump the module version 68 | "Updating Module version to $BuildVersion" 69 | Update-Metadata -Path $DestinationManifest -PropertyName ModuleVersion -Value $BuildVersion 70 | 71 | if (Test-Path "$ModuleFolder\Public\") { 72 | "Populating AliasesToExport and FunctionsToExport" 73 | $FunctionFiles = Get-ChildItem "$ModuleFolder\Public\" -Filter '*.ps1' -Recurse | 74 | Where-Object { $_.Name -notmatch '\.tests{0,1}\.ps1' } 75 | $ExportFunctions = [System.Collections.Generic.List[String]]::new() 76 | $ExportAliases = [System.Collections.Generic.List[String]]::new() 77 | foreach ($FunctionFile in $FunctionFiles) { 78 | "- Processing $($FunctionFile.FullName)" 79 | $AST = [System.Management.Automation.Language.Parser]::ParseFile($FunctionFile.FullName, [ref]$null, [ref]$null) 80 | $Functions = $AST.FindAll( { 81 | $args[0] -is [System.Management.Automation.Language.FunctionDefinitionAst] 82 | }, $true) 83 | if ($Functions.Name) { 84 | $ExportFunctions.Add($Functions.Name) 85 | } 86 | $Aliases = $AST.FindAll( { 87 | $args[0] -is [System.Management.Automation.Language.AttributeAst] -and 88 | $args[0].parent -is [System.Management.Automation.Language.ParamBlockAst] -and 89 | $args[0].TypeName.FullName -eq 'alias' 90 | }, $true) 91 | if ($Aliases.PositionalArguments.value) { 92 | $ExportAliases.Add($Aliases.PositionalArguments.value) 93 | } 94 | } 95 | "- Running Update-MetaData -Path $DestinationManifest -PropertyName FunctionsToExport -Value : `r`n - {0}" -f ($ExportFunctions -Join "`r`n - ") 96 | Update-MetaData -Path $DestinationManifest -PropertyName FunctionsToExport -Value $ExportFunctions 97 | "- Update-Metadata -Path $DestinationManifest -PropertyName AliasesToExport -Value : `r`n - {0}" -f ($ExportAliases -Join "`r`n - ") 98 | Update-Metadata -Path $DestinationManifest -PropertyName AliasesToExport -Value $ExportAliases 99 | } Else { 100 | "$ModuleFolder\Public\ not found. No public functions to import" 101 | } 102 | 103 | "Populating $DestinationRootModule" 104 | # Scan the Enums, Classes,Public, and Private folders and add 105 | # all files contents to $DestinationRootModule 106 | $Params = @{ 107 | Path = @( 108 | "$ModuleFolder\Enums\" 109 | "$ModuleFolder\Classes\" 110 | "$ModuleFolder\Public\" 111 | "$ModuleFolder\Private\" 112 | ) 113 | Filter = '*.ps1' 114 | Recurse = $true 115 | ErrorAction = 'SilentlyContinue' 116 | } 117 | Get-ChildItem @Params | 118 | Where-Object { $_.Name -notmatch '\.tests{0,1}\.ps1' } | 119 | Get-Content | 120 | Set-Content -Path $DestinationRootModule -Encoding UTF8 121 | # Add Content of src psm1 to the end of the destination psm1 122 | Get-Content $SourceModuleRoot | Add-Content -Path $DestinationRootModule -Encoding UTF8 123 | } 124 | 125 | Task Test -depends Init { 126 | $lines 127 | "`n`tSTATUS: Testing with PowerShell $PSVersion" 128 | # Gather test results. Store them in a variable and file 129 | $Timestamp = Get-date -uformat "%Y%m%d-%H%M%S" 130 | $TestFile = "TestResults_PS$PSVersion`_$TimeStamp.xml" 131 | $Params = @{ 132 | Script = "$ProjectRoot\Tests" 133 | PassThru = $true 134 | OutputFormat = 'NUnitXml' 135 | OutputFile = "$ProjectRoot\bin\$TestFile" 136 | Tag = 'Unit' 137 | Show = 'Fails' 138 | CodeCoverage = $DestinationRootModule 139 | } 140 | $TestResults = Invoke-Pester @Params 141 | 142 | # In Appveyor? Upload our tests! #Abstract this into a function? 143 | If ($ENV:BHBuildSystem -eq 'AppVeyor') { 144 | "Uploading $ProjectRoot\bin\$TestFile to AppVeyor" 145 | "JobID: $env:APPVEYOR_JOB_ID" 146 | (New-Object 'System.Net.WebClient').UploadFile("https://ci.appveyor.com/api/testresults/nunit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path "$ProjectRoot\bin\$TestFile")) 147 | } 148 | Remove-Item "$ProjectRoot\bin\$TestFile" -Force -ErrorAction SilentlyContinue 149 | 150 | " " 151 | } 152 | 153 | Task BuildDocs -depends Init, Build { 154 | $lines 155 | Import-Module $DestinationManifest -Force -Global 156 | 157 | $Params = @{ 158 | Module = $ModuleName 159 | ErrorAction = 'SilentlyContinue' 160 | AlphabeticParamsOrder = $true 161 | WithModulePage = $true 162 | OutputFolder = $DocsFolder 163 | } 164 | New-MarkdownHelp @Params 165 | 166 | $Params = @{ 167 | Path = $DocsFolder 168 | RefreshModulePage = $true 169 | AlphabeticParamsOrder = $true 170 | } 171 | Update-MarkdownHelpModule @Params 172 | 173 | $Params = @{ 174 | Path = $DocsFolder 175 | Force = $true 176 | OutputPath = $DestinationFolder 177 | } 178 | New-ExternalHelp @Params 179 | "`n" 180 | } 181 | 182 | Task TestDocs -depends Init { 183 | $lines 184 | "Running Documentation tests`n" 185 | $Timestamp = Get-date -uformat "%Y%m%d-%H%M%S" 186 | $TestFile = "TestResults_PS$PSVersion`_$TimeStamp.xml" 187 | $Params = @{ 188 | Script = "$ProjectRoot\Tests" 189 | PassThru = $true 190 | Tag = 'Documentation' 191 | OutputFormat = 'NUnitXml' 192 | OutputFile = "$ProjectRoot\bin\$TestFile" 193 | Show = 'Fails' 194 | } 195 | $TestResults = Invoke-Pester @Params 196 | " " 197 | If ($ENV:BHBuildSystem -eq 'AppVeyor') { 198 | "Uploading $ProjectRoot\bin\$TestFile to AppVeyor" 199 | "JobID: $env:APPVEYOR_JOB_ID" 200 | (New-Object 'System.Net.WebClient').UploadFile("https://ci.appveyor.com/api/testresults/nunit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path "$ProjectRoot\bin\$TestFile")) 201 | } 202 | Remove-Item "$ProjectRoot\bin\$TestFile" -Force -ErrorAction SilentlyContinue 203 | " " 204 | } 205 | 206 | Task Deploy -depends Init { 207 | $lines 208 | 209 | # Gate deployment 210 | if ( 211 | $ENV:BHBuildSystem -ne 'Unknown' -and 212 | $ENV:BHBranchName -eq "master" -and 213 | $ENV:BHCommitMessage -match '!deploy' 214 | ) { 215 | Import-Module -Force -Global $DestinationFolder 216 | $Params = @{ 217 | Path = $ProjectRoot 218 | Force = $true 219 | } 220 | 221 | Invoke-PSDeploy @Verbose @Params 222 | } else { 223 | "Skipping deployment: To deploy, ensure that...`n" + 224 | "`t* You are in a known build system (Current: $ENV:BHBuildSystem)`n" + 225 | "`t* You are committing to the master branch (Current: $ENV:BHBranchName) `n" + 226 | "`t* Your commit message includes !deploy (Current: $ENV:BHCommitMessage)" 227 | } 228 | "`n" 229 | } 230 | -------------------------------------------------------------------------------- /src/BetterTls/BetterTls.psd1: -------------------------------------------------------------------------------- 1 | # 2 | # Module manifest for module 'BetterTls' 3 | # 4 | # Generated by: Mark Kraus 5 | # 6 | # Generated on: 3/23/2018 7 | # 8 | 9 | @{ 10 | 11 | # Script module or binary module file associated with this manifest. 12 | RootModule = 'BetterTls.psm1' 13 | 14 | # Version number of this module. 15 | ModuleVersion = '0.0.1' 16 | 17 | # Supported PSEditions 18 | # CompatiblePSEditions = @() 19 | 20 | # ID used to uniquely identify this module 21 | GUID = 'db2a59b5-d629-43ae-a8a8-cc34766aa00e' 22 | 23 | # Author of this module 24 | Author = 'Mark Kraus' 25 | 26 | # Company or vendor of this module 27 | CompanyName = 'Unknown' 28 | 29 | # Copyright statement for this module 30 | Copyright = 'Copyright (c) Mark Kraus. All rights reserved.' 31 | 32 | # Description of the functionality provided by this module 33 | Description = 'PowerShell Module to Enable TLS 1.1 and 1.2 for Use in Windows PowerShell Where Neither are Enabled by Default' 34 | 35 | # Minimum version of the PowerShell engine required by this module 36 | # PowerShellVersion = '' 37 | 38 | # Name of the PowerShell host required by this module 39 | # PowerShellHostName = '' 40 | 41 | # Minimum version of the PowerShell host required by this module 42 | # PowerShellHostVersion = '' 43 | 44 | # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. 45 | # DotNetFrameworkVersion = '' 46 | 47 | # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. 48 | # CLRVersion = '' 49 | 50 | # Processor architecture (None, X86, Amd64) required by this module 51 | # ProcessorArchitecture = '' 52 | 53 | # Modules that must be imported into the global environment prior to importing this module 54 | # RequiredModules = @() 55 | 56 | # Assemblies that must be loaded prior to importing this module 57 | # RequiredAssemblies = @() 58 | 59 | # Script files (.ps1) that are run in the caller's environment prior to importing this module. 60 | # ScriptsToProcess = @() 61 | 62 | # Type files (.ps1xml) to be loaded when importing this module 63 | # TypesToProcess = @() 64 | 65 | # Format files (.ps1xml) to be loaded when importing this module 66 | # FormatsToProcess = @() 67 | 68 | # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess 69 | # NestedModules = @() 70 | 71 | # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. 72 | FunctionsToExport = @( 73 | 'Disable-Tls' 74 | 'Enable-Tls' 75 | 'Get-Tls' 76 | 'Set-Tls' 77 | ) 78 | 79 | # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. 80 | # CmdletsToExport = @() 81 | 82 | # Variables to export from this module 83 | # VariablesToExport = @() 84 | 85 | # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. 86 | AliasesToExport = @() 87 | 88 | # DSC resources to export from this module 89 | # DscResourcesToExport = @() 90 | 91 | # List of all modules packaged with this module 92 | # ModuleList = @() 93 | 94 | # List of all files packaged with this module 95 | # FileList = @() 96 | 97 | # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. 98 | PrivateData = @{ 99 | 100 | PSData = @{ 101 | 102 | # Tags applied to this module. These help with module discovery in online galleries. 103 | Tags = @('Security', 'WebCmdlets', 'Utility', 'TLS') 104 | 105 | # A URL to the license for this module. 106 | LicenseUri = 'https://github.com/markekraus/BetterTls/blob/master/LICENSE' 107 | 108 | # A URL to the main website for this project. 109 | ProjectUri = 'https://github.com/markekraus/BetterTls' 110 | 111 | # A URL to an icon representing this module. 112 | # IconUri = '' 113 | 114 | # ReleaseNotes of this module 115 | # ReleaseNotes = '' 116 | 117 | } # End of PSData hashtable 118 | 119 | } # End of PrivateData hashtable 120 | 121 | # HelpInfo URI of this module 122 | # HelpInfoURI = '' 123 | 124 | # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. 125 | # DefaultCommandPrefix = '' 126 | 127 | } 128 | 129 | -------------------------------------------------------------------------------- /src/BetterTls/BetterTls.psm1: -------------------------------------------------------------------------------- 1 | #lala -------------------------------------------------------------------------------- /src/BetterTls/Private/Clear-TlsOptionCache.ps1: -------------------------------------------------------------------------------- 1 | function Clear-TlsOptionCache { 2 | [CmdletBinding()] 3 | [OutputType()] 4 | param () 5 | end { 6 | Write-Verbose 'Clearing TLS Options Cache.' 7 | $Script:Options = $null 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/BetterTls/Private/Get-TlsOptionCache.ps1: -------------------------------------------------------------------------------- 1 | function Get-TlsOptionCache { 2 | [CmdletBinding()] 3 | [OutputType([System.Collections.Hashtable])] 4 | param () 5 | end { 6 | if (-Not $Script:options) { 7 | Write-Verbose 'Generating TLS Options Cache.' 8 | $Script:Options = @{} 9 | Foreach ($Name in [System.Enum]::GetNames([System.Net.SecurityProtocolType])) { 10 | $Script:Options[$Name] = [System.Net.SecurityProtocolType]::$Name 11 | Write-Verbose "Added '$Name'." 12 | } 13 | } 14 | Write-Verbose "Retrieving TLS Option Cache." 15 | $Script:Options 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/BetterTls/Public/Disable-Tls.ps1: -------------------------------------------------------------------------------- 1 | function Disable-Tls { 2 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseSingularNouns", "", Justification = "TLS is singular.")] 3 | [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] 4 | [OutputType([System.Net.SecurityProtocolType])] 5 | param ( 6 | [Switch]$Tls12, 7 | [Switch]$Tls11, 8 | [Switch]$Tls, 9 | [Switch]$Ssl3, 10 | [switch]$PassThru 11 | ) 12 | process { 13 | $Options = Get-TlsOptionCache 14 | $NewSettings = Get-Tls 15 | switch ($True) { 16 | $Tls12.IsPresent { $NewSettings = $NewSettings -band -bnot $Options.Tls12 } 17 | $Tls11.IsPresent { $NewSettings = $NewSettings -band -bnot $Options.Tls11 } 18 | $Tls.IsPresent { $NewSettings = $NewSettings -band -bnot $Options.Tls } 19 | $Ssl3.IsPresent { $NewSettings = $NewSettings -band -bnot $Options.Ssl3 } 20 | } 21 | Set-Tls -SecurityProtocol $NewSettings -PassThru:($PassThru.IsPresent) -Caller $PSCmdlet 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/BetterTls/Public/Enable-Tls.ps1: -------------------------------------------------------------------------------- 1 | function Enable-Tls { 2 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseSingularNouns", "", Justification = "TLS is singular.")] 3 | [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] 4 | [OutputType([System.Net.SecurityProtocolType])] 5 | param ( 6 | [Switch]$Tls12, 7 | [Switch]$Tls11, 8 | [Switch]$Tls, 9 | [Switch]$Ssl3, 10 | [switch]$PassThru 11 | ) 12 | process { 13 | $Options = Get-TlsOptionCache 14 | $NewSettings = Get-Tls 15 | switch ($True) { 16 | $Tls12.IsPresent { $NewSettings = $NewSettings -bor $Options.Tls12 } 17 | $Tls11.IsPresent { $NewSettings = $NewSettings -bor $Options.Tls11 } 18 | $Tls.IsPresent { $NewSettings = $NewSettings -bor $Options.Tls } 19 | $Ssl3.IsPresent { $NewSettings = $NewSettings -bor $Options.Ssl3 } 20 | } 21 | Set-Tls -SecurityProtocol $NewSettings -PassThru:($PassThru.IsPresent) -Caller $PSCmdlet 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/BetterTls/Public/Get-Tls.ps1: -------------------------------------------------------------------------------- 1 | function Get-Tls { 2 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseSingularNouns", "", Justification = "TLS is singular.")] 3 | [CmdletBinding()] 4 | [OutputType([System.Net.SecurityProtocolType])] 5 | param () 6 | end { 7 | Write-Verbose "Retrieving current TLS Settings." 8 | $Current = [System.Net.ServicePointManager]::SecurityProtocol 9 | Write-Verbose "Current TLS Settings: $Current" 10 | $Current 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/BetterTls/Public/Set-Tls.ps1: -------------------------------------------------------------------------------- 1 | function Set-Tls { 2 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseSingularNouns", "", Justification = "TLS is singular.")] 3 | [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High', DefaultParameterSetName = 'Switch')] 4 | [OutputType([System.Net.SecurityProtocolType])] 5 | param ( 6 | [Parameter(ParameterSetName = 'Switch')] 7 | [Switch]$Tls12, 8 | [Parameter(ParameterSetName = 'Switch')] 9 | [Switch]$Tls11, 10 | [Parameter(ParameterSetName = 'Switch')] 11 | [Switch]$Tls, 12 | [Parameter(ParameterSetName = 'Switch')] 13 | [Switch]$Ssl3, 14 | 15 | [Parameter(ParameterSetName = 'SecurityProtocol', Mandatory)] 16 | [System.Net.SecurityProtocolType] 17 | $SecurityProtocol, 18 | 19 | [Parameter(ParameterSetName = 'Switch')] 20 | [Parameter(ParameterSetName = 'SecurityProtocol')] 21 | [switch]$PassThru, 22 | 23 | [Parameter(DontShow, ParameterSetName = 'Switch')] 24 | [Parameter(DontShow, ParameterSetName = 'SecurityProtocol')] 25 | [System.Management.Automation.PSCmdlet] 26 | $Caller 27 | ) 28 | process { 29 | if (-not $Caller) { 30 | $Caller = $PSCmdlet 31 | } 32 | $Options = Get-TlsOptionCache 33 | $TlsSettings = Get-Tls 34 | if ( $PSCmdlet.ParameterSetName -eq 'Switch') { 35 | switch ($True) { 36 | $Tls12.IsPresent { $TlsSettings = $TlsSettings -bor $Options.Tls12 } 37 | $Tls11.IsPresent { $TlsSettings = $TlsSettings -bor $Options.Tls11 } 38 | $Tls.IsPresent { $TlsSettings = $TlsSettings -bor $Options.Tls } 39 | $Ssl3.IsPresent { $TlsSettings = $TlsSettings -bor $Options.Ssl3 } 40 | } 41 | switch ($False) { 42 | $Tls12.IsPresent { $TlsSettings = $TlsSettings -band -bnot $Options.Tls12 } 43 | $Tls11.IsPresent { $TlsSettings = $TlsSettings -band -bnot $Options.Tls11 } 44 | $Tls.IsPresent { $TlsSettings = $TlsSettings -band -bnot $Options.Tls } 45 | $Ssl3.IsPresent { $TlsSettings = $TlsSettings -band -bnot $Options.Ssl3 } 46 | } 47 | Set-Tls -SecurityProtocol $TlsSettings -PassThru:($PassThru.IsPresent) -Caller $Caller 48 | } 49 | if ( $PSCmdlet.ParameterSetName -eq 'SecurityProtocol' ) { 50 | if ($TlsSettings -eq $SecurityProtocol) { 51 | Write-Verbose "TLS Settings unchanged." 52 | } elseif ($Caller.ShouldProcess("Changing [System.Net.ServicePointManager]::SecurityProtocol from '$TlsSettings' to '$SecurityProtocol'")) { 53 | [System.Net.ServicePointManager]::SecurityProtocol = $SecurityProtocol 54 | } 55 | if ($PassThru.IsPresent) { 56 | Get-Tls 57 | } 58 | } 59 | } 60 | } 61 | --------------------------------------------------------------------------------