feat(connect): add -SkipCertificateCheck and -AllowInsecureTransport switches #11

Merged
gsadmin merged 2 commits from dev into main 2026-06-05 20:49:04 +00:00
5 changed files with 104 additions and 3 deletions
Showing only changes of commit 1270c9099c - Show all commits
@@ -84,5 +84,38 @@ namespace PSInfisicalAPI.Tests
Assert.Equal("explicit-org", cmdlet.CallResolveOrganizationId(ConnectionWithDefaults(), "explicit-org"));
Assert.Empty(logger.VerboseEntries);
}
[Fact]
public void InfisicalConnection_Defaults_TransportFlags_To_False()
{
InfisicalConnection connection = new InfisicalConnection();
Assert.False(connection.SkipCertificateCheck);
Assert.False(connection.AllowInsecureTransport);
}
[Fact]
public void ShouldSkipCertificateCheck_Reads_From_Current_Session()
{
InfisicalConnection previous = InfisicalSessionManager.Current;
try
{
TestCmdlet cmdlet = CreateCmdletWith(new RecordingLogger());
MethodInfo virt = typeof(InfisicalCmdletBase).GetMethod("ShouldSkipCertificateCheck", BindingFlags.NonPublic | BindingFlags.Instance);
InfisicalSessionManager.SetCurrent(null);
Assert.False((bool)virt.Invoke(cmdlet, null));
InfisicalConnection session = ConnectionWithDefaults();
session.IsConnected = true;
session.SkipCertificateCheck = true;
InfisicalSessionManager.SetCurrent(session);
Assert.True((bool)virt.Invoke(cmdlet, null));
}
finally
{
InfisicalSessionManager.SetCurrent(previous);
}
}
}
}
@@ -62,12 +62,24 @@ namespace PSInfisicalAPI.Cmdlets
[Parameter]
public SwitchParameter PassThru { get; set; }
[Parameter]
public SwitchParameter SkipCertificateCheck { get; set; }
[Parameter]
public SwitchParameter AllowInsecureTransport { get; set; }
protected override bool ShouldSkipCertificateCheck()
{
return SkipCertificateCheck.IsPresent;
}
protected override void ProcessRecord()
{
try
{
ResolveMissingParametersFromEnvironment();
ValidateRequiredParameters();
ValidateTransportSafety();
IInfisicalAuthProvider provider;
InfisicalAuthenticationRequest request;
@@ -179,7 +191,9 @@ namespace PSInfisicalAPI.Cmdlets
ConnectedAtUtc = DateTimeOffset.UtcNow,
ExpiresAtUtc = authResult.ExpiresAtUtc,
IsConnected = true,
AccessToken = authResult.AccessToken
AccessToken = authResult.AccessToken,
SkipCertificateCheck = SkipCertificateCheck.IsPresent,
AllowInsecureTransport = AllowInsecureTransport.IsPresent
};
InfisicalSessionManager.SetCurrent(connection);
@@ -195,6 +209,26 @@ namespace PSInfisicalAPI.Cmdlets
}
}
private void ValidateTransportSafety()
{
bool isHttp = BaseUri != null && string.Equals(BaseUri.Scheme, "http", StringComparison.OrdinalIgnoreCase);
if (isHttp && !AllowInsecureTransport.IsPresent)
{
throw new InfisicalConfigurationException("BaseUri '" + BaseUri + "' is not HTTPS. Re-run Connect-Infisical with -AllowInsecureTransport to permit plaintext.");
}
if (SkipCertificateCheck.IsPresent)
{
Logger.Warning(Component, "SkipCertificateCheck is enabled. TLS certificate validation is disabled for this session. Do not use in production.");
}
if (AllowInsecureTransport.IsPresent && isHttp)
{
Logger.Warning(Component, "AllowInsecureTransport is enabled and BaseUri uses HTTP. Credentials and secrets will traverse the network unencrypted. Do not use in production.");
}
}
private void ResolveMissingParametersFromEnvironment()
{
bool tokenSet = string.Equals(ParameterSetName, ParameterSetToken, StringComparison.Ordinal);
@@ -31,13 +31,19 @@ namespace PSInfisicalAPI.Cmdlets
{
if (_httpClient == null)
{
_httpClient = new InfisicalHttpClient(Logger);
_httpClient = new InfisicalHttpClient(Logger, 100, ShouldSkipCertificateCheck());
}
return _httpClient;
}
}
protected virtual bool ShouldSkipCertificateCheck()
{
InfisicalConnection current = InfisicalSessionManager.Current;
return current != null && current.SkipCertificateCheck;
}
protected void ThrowTerminatingForException(string component, string operation, Exception exception)
{
InfisicalErrorDetails details = InfisicalErrorHandler.BuildDetails(component, operation, exception);
@@ -15,6 +15,8 @@ namespace PSInfisicalAPI.Connections
public DateTimeOffset ConnectedAtUtc { get; set; }
public DateTimeOffset? ExpiresAtUtc { get; set; }
public bool IsConnected { get; set; }
public bool SkipCertificateCheck { get; set; }
public bool AllowInsecureTransport { get; set; }
public Dictionary<string, string> ResolvedEndpointVersions { get; } = new Dictionary<string, string>(StringComparer.Ordinal);
+27 -1
View File
@@ -2,6 +2,8 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Reflection;
using System.Text;
using PSInfisicalAPI.Errors;
using PSInfisicalAPI.Logging;
@@ -11,13 +13,18 @@ namespace PSInfisicalAPI.Http
public sealed class InfisicalHttpClient : IInfisicalHttpClient
{
private const string Component = "HttpClient";
private static readonly PropertyInfo PerRequestCertCallbackProperty =
typeof(HttpWebRequest).GetProperty("ServerCertificateValidationCallback");
private readonly IInfisicalLogger _logger;
private readonly int _timeoutSeconds;
private readonly bool _skipCertificateCheck;
public InfisicalHttpClient(IInfisicalLogger logger, int timeoutSeconds = 100)
public InfisicalHttpClient(IInfisicalLogger logger, int timeoutSeconds = 100, bool skipCertificateCheck = false)
{
_logger = logger ?? NullInfisicalLogger.Instance;
_timeoutSeconds = timeoutSeconds;
_skipCertificateCheck = skipCertificateCheck;
}
public InfisicalHttpResponse Send(InfisicalHttpRequest request)
@@ -44,6 +51,11 @@ namespace PSInfisicalAPI.Http
webRequest.ReadWriteTimeout = _timeoutSeconds * 1000;
webRequest.UseDefaultCredentials = true;
if (_skipCertificateCheck)
{
ApplyInsecureCertificateBypass(webRequest);
}
IWebProxy systemProxy = WebRequest.GetSystemWebProxy();
if (systemProxy != null)
{
@@ -95,6 +107,20 @@ namespace PSInfisicalAPI.Http
}
}
private void ApplyInsecureCertificateBypass(HttpWebRequest webRequest)
{
RemoteCertificateValidationCallback callback = (sender, certificate, chain, errors) => true;
if (PerRequestCertCallbackProperty != null && PerRequestCertCallbackProperty.CanWrite)
{
PerRequestCertCallbackProperty.SetValue(webRequest, callback, null);
return;
}
_logger.Warning(Component, "Per-request ServerCertificateValidationCallback unavailable on this runtime; falling back to global ServicePointManager override for this process.");
ServicePointManager.ServerCertificateValidationCallback = callback;
}
private static void ApplyHeaders(HttpWebRequest webRequest, IDictionary<string, string> headers)
{
if (headers == null)