mirror of
https://github.com/portainer/portainer.git
synced 2025-08-05 13:55:21 +02:00
feat(gitops): allow to skip tls verification [EE-5023] (#8668)
This commit is contained in:
parent
17839aa473
commit
feab2a757e
44 changed files with 266 additions and 188 deletions
|
@ -56,6 +56,7 @@ angular.module('portainer.edge').factory('EdgeStackService', function EdgeStackS
|
|||
RepositoryAuthentication: repositoryOptions.RepositoryAuthentication,
|
||||
RepositoryUsername: repositoryOptions.RepositoryUsername,
|
||||
RepositoryPassword: repositoryOptions.RepositoryPassword,
|
||||
TLSSkipVerify: repositoryOptions.TLSSkipVerify,
|
||||
}
|
||||
).$promise;
|
||||
} catch (err) {
|
||||
|
|
|
@ -23,6 +23,7 @@ export default class CreateEdgeStackViewController {
|
|||
Groups: [],
|
||||
DeploymentType: 0,
|
||||
UseManifestNamespaces: false,
|
||||
TLSSkipVerify: false,
|
||||
};
|
||||
|
||||
this.EditorType = EditorType;
|
||||
|
@ -215,6 +216,7 @@ export default class CreateEdgeStackViewController {
|
|||
RepositoryAuthentication: this.formValues.RepositoryAuthentication,
|
||||
RepositoryUsername: this.formValues.RepositoryUsername,
|
||||
RepositoryPassword: this.formValues.RepositoryPassword,
|
||||
TLSSkipVerify: this.formValues.TLSSkipVerify,
|
||||
};
|
||||
return this.EdgeStackService.createStackFromGitRepository(
|
||||
{
|
||||
|
|
|
@ -59,6 +59,7 @@ class KubernetesDeployController {
|
|||
ComposeFilePathInRepository: '',
|
||||
Variables: {},
|
||||
AutoUpdate: parseAutoUpdateResponse(),
|
||||
TLSSkipVerify: false,
|
||||
};
|
||||
|
||||
this.ManifestDeployTypes = KubernetesDeployManifestTypes;
|
||||
|
@ -248,6 +249,7 @@ class KubernetesDeployController {
|
|||
};
|
||||
|
||||
if (method === KubernetesDeployRequestMethods.REPOSITORY) {
|
||||
payload.TLSSkipVerify = this.formValues.TLSSkipVerify;
|
||||
payload.RepositoryURL = this.formValues.RepositoryURL;
|
||||
payload.RepositoryReferenceName = this.formValues.RepositoryReferenceName;
|
||||
payload.RepositoryAuthentication = this.formValues.RepositoryAuthentication ? true : false;
|
||||
|
|
|
@ -355,6 +355,7 @@ angular.module('portainer.app').factory('StackService', [
|
|||
RepositoryPassword: repositoryOptions.RepositoryPassword,
|
||||
Env: env,
|
||||
FromAppTemplate: repositoryOptions.FromAppTemplate,
|
||||
TLSSkipVerify: repositoryOptions.TLSSkipVerify,
|
||||
};
|
||||
|
||||
if (repositoryOptions.AutoUpdate) {
|
||||
|
@ -382,6 +383,7 @@ angular.module('portainer.app').factory('StackService', [
|
|||
RepositoryPassword: repositoryOptions.RepositoryPassword,
|
||||
Env: env,
|
||||
FromAppTemplate: repositoryOptions.FromAppTemplate,
|
||||
TLSSkipVerify: repositoryOptions.TLSSkipVerify,
|
||||
};
|
||||
|
||||
if (repositoryOptions.AutoUpdate) {
|
||||
|
|
|
@ -44,6 +44,7 @@ class CreateCustomTemplateViewController {
|
|||
Type: 1,
|
||||
AccessControlData: new AccessControlFormData(),
|
||||
Variables: [],
|
||||
TLSSkipVerify: false,
|
||||
};
|
||||
|
||||
this.state = {
|
||||
|
|
|
@ -57,6 +57,7 @@ angular
|
|||
EnableWebhook: false,
|
||||
Variables: {},
|
||||
AutoUpdate: parseAutoUpdateResponse(),
|
||||
TLSSkipVerify: false,
|
||||
};
|
||||
|
||||
$scope.state = {
|
||||
|
@ -175,6 +176,7 @@ angular
|
|||
RepositoryUsername: $scope.formValues.RepositoryUsername,
|
||||
RepositoryPassword: $scope.formValues.RepositoryPassword,
|
||||
AutoUpdate: transformAutoUpdateViewModel($scope.formValues.AutoUpdate, $scope.state.webhookId),
|
||||
TLSSkipVerify: $scope.formValues.TLSSkipVerify,
|
||||
};
|
||||
|
||||
return StackService.createSwarmStackFromGitRepository(name, repositoryOptions, env, endpointId);
|
||||
|
@ -201,6 +203,7 @@ angular
|
|||
RepositoryUsername: $scope.formValues.RepositoryUsername,
|
||||
RepositoryPassword: $scope.formValues.RepositoryPassword,
|
||||
AutoUpdate: transformAutoUpdateViewModel($scope.formValues.AutoUpdate, $scope.state.webhookId),
|
||||
TLSSkipVerify: $scope.formValues.TLSSkipVerify,
|
||||
};
|
||||
|
||||
return StackService.createComposeStackFromGitRepository(name, repositoryOptions, env, endpointId);
|
||||
|
|
|
@ -35,6 +35,7 @@ export function PathSelector({
|
|||
repository: model.RepositoryURL,
|
||||
keyword: searchTerm,
|
||||
reference: model.RepositoryReferenceName,
|
||||
tlsSkipVerify: model.TLSSkipVerify,
|
||||
...creds,
|
||||
};
|
||||
const enabled = Boolean(
|
||||
|
|
|
@ -70,6 +70,7 @@ export function Primary({
|
|||
ComposeFilePathInRepository: '',
|
||||
NewCredentialName: '',
|
||||
SaveCredential: false,
|
||||
TLSSkipVerify: false,
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
@ -9,6 +9,7 @@ import { TimeWindowDisplay } from '@/react/portainer/gitops/TimeWindowDisplay';
|
|||
|
||||
import { FormSection } from '@@/form-components/FormSection';
|
||||
import { validateForm } from '@@/form-components/validate-form';
|
||||
import { SwitchField } from '@@/form-components/SwitchField';
|
||||
|
||||
import { GitCredential } from '../account/git-credentials/types';
|
||||
|
||||
|
@ -104,6 +105,19 @@ export function GitForm({
|
|||
)}
|
||||
|
||||
<TimeWindowDisplay />
|
||||
|
||||
<div className="form-group">
|
||||
<div className="col-sm-12">
|
||||
<SwitchField
|
||||
label="Skip TLS Verification"
|
||||
checked={value.TLSSkipVerify}
|
||||
onChange={(value) => handleChange({ TLSSkipVerify: value })}
|
||||
name="TLSSkipVerify"
|
||||
tooltip="Enabling this will allow skipping TLS validation for any self-signed certificate."
|
||||
labelClass="col-sm-3 col-lg-2"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</FormSection>
|
||||
);
|
||||
|
||||
|
@ -127,7 +141,18 @@ export function buildGitValidationSchema(
|
|||
): SchemaOf<GitFormModel> {
|
||||
return object({
|
||||
RepositoryURL: string()
|
||||
.url('Invalid Url')
|
||||
.test('valid URL', 'The URL must be a valid URL', (value) => {
|
||||
if (!value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
const url = new URL(value);
|
||||
return !!url.hostname;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.required('Repository URL is required'),
|
||||
RepositoryReferenceName: refFieldValidation(),
|
||||
ComposeFilePathInRepository: string().required(
|
||||
|
@ -136,5 +161,6 @@ export function buildGitValidationSchema(
|
|||
AdditionalFiles: array(string().required('Path is required')).default([]),
|
||||
RepositoryURLValid: boolean().default(false),
|
||||
AutoUpdate: autoUpdateValidation().nullable(),
|
||||
TLSSkipVerify: boolean().default(false),
|
||||
}).concat(gitAuthValidation(gitCredentials));
|
||||
}
|
||||
|
|
|
@ -40,14 +40,18 @@ export function GitFormUrlField({
|
|||
|
||||
const creds = getAuthentication(model);
|
||||
const [force, setForce] = useState(false);
|
||||
const repoStatusQuery = useCheckRepo(value, creds, force, {
|
||||
onSettled(isValid) {
|
||||
onChangeRepositoryValid(!!isValid);
|
||||
setForce(false);
|
||||
},
|
||||
// disabled check on CE since it's not supported
|
||||
enabled: isBE,
|
||||
});
|
||||
const repoStatusQuery = useCheckRepo(
|
||||
value,
|
||||
{ creds, force, tlsSkipVerify: model.TLSSkipVerify },
|
||||
{
|
||||
onSettled(isValid) {
|
||||
onChangeRepositoryValid(!!isValid);
|
||||
setForce(false);
|
||||
},
|
||||
// disabled check on CE since it's not supported
|
||||
enabled: isBE,
|
||||
}
|
||||
);
|
||||
|
||||
const [debouncedValue, debouncedOnChange] = useDebounce(value, onChange);
|
||||
|
||||
|
@ -115,7 +119,7 @@ export function useUrlValidation(force: boolean) {
|
|||
const model = context.parent as GitFormModel;
|
||||
|
||||
const creds = getAuthentication(model);
|
||||
return checkRepo(url, creds, force);
|
||||
return checkRepo(url, { creds, force });
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ export function RefSelector({
|
|||
const payload = {
|
||||
repository: model.RepositoryURL,
|
||||
stackId,
|
||||
tlsSkipVerify: model.TLSSkipVerify,
|
||||
...creds,
|
||||
};
|
||||
|
||||
|
|
|
@ -2,4 +2,5 @@ import { GitCredentialsModel } from '../types';
|
|||
|
||||
export interface RefFieldModel extends GitCredentialsModel {
|
||||
RepositoryURL: string;
|
||||
TLSSkipVerify?: boolean;
|
||||
}
|
||||
|
|
|
@ -8,19 +8,23 @@ interface Creds {
|
|||
password?: string;
|
||||
gitCredentialId?: number;
|
||||
}
|
||||
interface CheckRepoOptions {
|
||||
creds?: Creds;
|
||||
force?: boolean;
|
||||
tlsSkipVerify?: boolean;
|
||||
}
|
||||
|
||||
export function useCheckRepo(
|
||||
url: string,
|
||||
creds: Creds,
|
||||
force: boolean,
|
||||
options: CheckRepoOptions,
|
||||
{
|
||||
enabled,
|
||||
onSettled,
|
||||
}: { enabled?: boolean; onSettled?(isValid?: boolean): void } = {}
|
||||
) {
|
||||
return useQuery(
|
||||
['git_repo_valid', url, creds, force],
|
||||
() => checkRepo(url, creds, force),
|
||||
['git_repo_valid', url, options],
|
||||
() => checkRepo(url, options),
|
||||
{
|
||||
enabled: !!url && enabled,
|
||||
onSettled,
|
||||
|
@ -31,13 +35,12 @@ export function useCheckRepo(
|
|||
|
||||
export async function checkRepo(
|
||||
repository: string,
|
||||
creds: Creds,
|
||||
force: boolean
|
||||
{ force, ...options }: CheckRepoOptions
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
await axios.post<string[]>(
|
||||
'/gitops/repo/refs',
|
||||
{ repository, ...creds },
|
||||
{ repository, tlsSkipVerify: options.tlsSkipVerify, ...options.creds },
|
||||
force ? { params: { force } } : {}
|
||||
);
|
||||
return true;
|
||||
|
@ -45,11 +48,12 @@ export async function checkRepo(
|
|||
throw parseAxiosError(error as Error, '', (axiosError: AxiosError) => {
|
||||
let details = axiosError.response?.data.details;
|
||||
|
||||
const { creds = {} } = options;
|
||||
// If no credentials were provided alter error from git to indicate repository is not found or is private
|
||||
if (
|
||||
!(creds.username && creds.password) &&
|
||||
details ===
|
||||
'Authentication failed, please ensure that the git credentials are correct.'
|
||||
'authentication failed, please ensure that the git credentials are correct'
|
||||
) {
|
||||
details =
|
||||
'Git repository could not be found or is private, please ensure that the URL is correct or credentials are provided.';
|
||||
|
|
|
@ -6,6 +6,7 @@ interface RefsPayload {
|
|||
repository: string;
|
||||
username?: string;
|
||||
password?: string;
|
||||
tlsSkipVerify?: boolean;
|
||||
}
|
||||
|
||||
export function useGitRefs<T = string[]>(
|
||||
|
|
|
@ -60,6 +60,7 @@ export interface GitFormModel extends GitAuthModel {
|
|||
|
||||
SaveCredential?: boolean;
|
||||
NewCredentialName?: string;
|
||||
TLSSkipVerify: boolean;
|
||||
|
||||
/**
|
||||
* Auto update
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue