Skip to content

Commit

Permalink
Реализация правила Обращение к методам привилегированных модулей
Browse files Browse the repository at this point in the history
добавлена отдельная мини-конфигурация для тестов

closes #1870
  • Loading branch information
artbear committed Oct 24, 2023
1 parent 1c83f52 commit 73745fb
Show file tree
Hide file tree
Showing 15 changed files with 697 additions and 0 deletions.
26 changes: 26 additions & 0 deletions docs/diagnostics/PrivilegedModuleMethodCall.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# <Diagnostic name> (PrivilegedModuleMethodCall)

<!-- Блоки выше заполняются автоматически, не трогать -->
## Описание диагностики
<!-- Описание диагностики заполняется вручную. Необходимо понятным языком описать смысл и схему работу -->
При обращении к публичным процедурам и функциям привилегированных общих модулей могут нарушаться ограничения конфигурации по правам и ролям конфигурации, решения 1С.
Необходимо провалидировать подобные обращения для исключения обхода ограничений.

## Примеры
<!-- В данном разделе приводятся примеры, на которые диагностика срабатывает, а также можно привести пример, как можно исправить ситуацию -->
Например, в конфигурации существует привилегированный модуль выполнения заданий с именем `Задания`.
В этом модуле есть публичная функция `Функция ДобавитьЗадание(Знач ИмяМетода, Знач Параметры) Экспорт`.
Какой-то код конфигурации или расширения обращается к этому методу `Задания.ДобавитьЗадание("МетодДляВыполнения", Параметры);`

Необходимо проанализировать код и убедиться в том, что:
- указан правильный метод для выполнения задания - `МетодДляВыполнения`
- метод `МетодДляВыполнения` для выполнения задания не выполняет деструктивных действий
- и не выдает пользователям данные, запрещенные ограничениями конфигурации

## Источники
<!-- Необходимо указывать ссылки на все источники, из которых почерпнута информация для создания диагностики -->
<!-- Примеры источников
* Источник: [Стандарт: Тексты модулей](https://its.1c.ru/db/v8std#content:456:hdoc)
* Полезная информация: [Отказ от использования модальных окон](https://its.1c.ru/db/metod8dev#content:5272:hdoc)
* Источник: [Cognitive complexity, ver. 1.4](https://www.sonarsource.com/docs/CognitiveComplexity.pdf) -->
16 changes: 16 additions & 0 deletions docs/en/diagnostics/PrivilegedModuleMethodCall.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# <Diagnostic name> (PrivilegedModuleMethodCall)

<!-- Блоки выше заполняются автоматически, не трогать -->
## Description
<!-- Описание диагностики заполняется вручную. Необходимо понятным языком описать смысл и схему работу -->

## Examples
<!-- В данном разделе приводятся примеры, на которые диагностика срабатывает, а также можно привести пример, как можно исправить ситуацию -->

## Sources
<!-- Необходимо указывать ссылки на все источники, из которых почерпнута информация для создания диагностики -->
<!-- Примеры источников
* Источник: [Стандарт: Тексты модулей](https://its.1c.ru/db/v8std#content:456:hdoc)
* Полезная информация: [Отказ от использования модальных окон](https://its.1c.ru/db/metod8dev#content:5272:hdoc)
* Источник: [Cognitive complexity, ver. 1.4](https://www.sonarsource.com/docs/CognitiveComplexity.pdf) -->
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* This file is a part of BSL Language Server.
*
* Copyright (c) 2018-2023
* Alexey Sosnoviy <labotamy@gmail.com>, Nikita Fedkin <nixel2007@gmail.com> and contributors
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*
* BSL Language Server is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* BSL Language Server is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with BSL Language Server.
*/
package com.github._1c_syntax.bsl.languageserver.diagnostics;

import com.github._1c_syntax.bsl.languageserver.context.symbol.ModuleSymbol;
import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticMetadata;
import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticScope;
import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticSeverity;
import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticTag;
import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticType;
import com.github._1c_syntax.bsl.languageserver.references.ReferenceIndex;
import com.github._1c_syntax.bsl.languageserver.references.model.Reference;
import com.github._1c_syntax.bsl.types.ModuleType;
import com.github._1c_syntax.mdclasses.mdo.MDCommonModule;
import lombok.RequiredArgsConstructor;
import org.eclipse.lsp4j.SymbolKind;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@DiagnosticMetadata(
type = DiagnosticType.VULNERABILITY,
severity = DiagnosticSeverity.MAJOR,
minutesToFix = 60,
tags = {
DiagnosticTag.SUSPICIOUS
},
scope = DiagnosticScope.BSL
)
@RequiredArgsConstructor
public class PrivilegedModuleMethodCallDiagnostic extends AbstractDiagnostic {
private final ReferenceIndex referenceIndex;
private List<ModuleSymbol> privilegedModuleSymbols = new ArrayList<>();

private static boolean isReferenceToModules(Reference reference, List<ModuleSymbol> privilegedModuleSymbols) {
return reference.getSourceDefinedSymbol()
.flatMap(sourceDefinedSymbol -> sourceDefinedSymbol.getRootParent(SymbolKind.Module))
.filter(ModuleSymbol.class::isInstance)
.map(ModuleSymbol.class::cast)
.filter(privilegedModuleSymbols::contains)
.isPresent();
}

@Override
protected void check() {
if (privilegedModuleSymbols.isEmpty()){
privilegedModuleSymbols = getPrivilegedModuleSymbols();
}
if (privilegedModuleSymbols.isEmpty()){
return;
}

referenceIndex.getReferencesFrom(documentContext.getUri(), SymbolKind.Method).stream()
.filter(reference -> isReferenceToModules(reference, privilegedModuleSymbols))
.forEach(this::fireIssue);
}

private List<ModuleSymbol> getPrivilegedModuleSymbols() {
return documentContext.getServerContext().getConfiguration().getCommonModules()
.values().stream()
.filter(MDCommonModule::isPrivileged)
.flatMap(mdCommonModule -> getPrivilegedModuleSymbol(mdCommonModule).stream())
.toList();
}

private Optional<ModuleSymbol> getPrivilegedModuleSymbol(MDCommonModule mdCommonModule) {
return documentContext.getServerContext().getDocument(
mdCommonModule.getMdoReference().getMdoRef(), ModuleType.CommonModule)
.map(documentContext1 -> documentContext1.getSymbolTree().getModule());
}

private void fireIssue(Reference reference) {
diagnosticStorage.addDiagnostic(reference.getSelectionRange(),
info.getMessage(reference.getSymbol().getName()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
diagnosticMessage=Check the %s method access of the privileged module
diagnosticName=Accessing privileged module methods
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
diagnosticMessage=Проверьте обращение к методу %s привилегированного модуля
diagnosticName=Обращение к методам привилегированных модулей
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* This file is a part of BSL Language Server.
*
* Copyright (c) 2018-2023
* Alexey Sosnoviy <labotamy@gmail.com>, Nikita Fedkin <nixel2007@gmail.com> and contributors
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*
* BSL Language Server is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* BSL Language Server is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with BSL Language Server.
*/
package com.github._1c_syntax.bsl.languageserver.diagnostics;

import org.eclipse.lsp4j.Diagnostic;
import org.junit.jupiter.api.Test;

import java.util.List;

import static com.github._1c_syntax.bsl.languageserver.util.Assertions.assertThat;

class PrivilegedModuleMethodCallDiagnosticTest extends AbstractDiagnosticTest<PrivilegedModuleMethodCallDiagnostic> {
private static final String PATH_TO_METADATA = "src/test/resources/metadata/privilegedModules";

PrivilegedModuleMethodCallDiagnosticTest() {
super(PrivilegedModuleMethodCallDiagnostic.class);
}

@Test
void test() {
initServerContext(PATH_TO_METADATA);

List<Diagnostic> diagnostics = getDiagnostics();

assertThat(diagnostics).hasSize(2);
assertThat(diagnostics, true)
.hasMessageOnRange("Проверьте обращение к методу ПубличнаяФункция привилегированного модуля", 3, 40, 56)
.hasMessageOnRange("Проверьте обращение к методу ПубличнаяПроцедура привилегированного модуля", 4, 29, 47);
}

@Test
void testWithoutMetadata() {

List<Diagnostic> diagnostics = getDiagnostics();
assertThat(diagnostics).isEmpty();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#Область ПрограммныйИнтерфейс

Функция Тест1()
Значение = ПривилегированныйМодуль1.ПубличнаяФункция(); // ошибка
ПривилегированныйМодуль1.ПубличнаяПроцедура(); // ошибка
КонецФункции

Процедура Тест2()
Значение = ПривилегированныйМодуль1.ПриватнаяФункция(); // не ошибка в данном правиле
ПривилегированныйМодуль1.ПриватнаяПроцедура(); // не ошибка в данном правиле
КонецПроцедуры

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

#КонецОбласти
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.11">
<CommonModule uuid="8bec7488-90ab-484a-bdc9-ce1584d95925">
<Properties>
<Name>ОбщийМодуль2</Name>
<Synonym/>
<Comment/>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>false</ExternalConnection>
<ClientOrdinaryApplication>false</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@

/////Описание
/////
/////

#Область ОписаниеПеременных




#КонецОбласти

#Область ПрограммныйИнтерфейс
// Код процедур и функций
#КонецОбласти

#Область СлужебныйПрограммныйИнтерфейс
// Код процедур и функций
#КонецОбласти

#Область СлужебныеПроцедурыИФункции
// Код процедур и функций
#КонецОбласти


#Region EventHandlers
// Enter code here.
#EndRegion

#Region Internal
// Enter code here.
#EndRegion

#Область ОбработчикиСобытийФормы
// Код процедур и функций
#КонецОбласти

#Область ОбработчикиСобытийЭлементовШапкиФормы
// Код процедур и функций
#КонецОбласти

#Область ОбработчикиСобытийЭлементовТаблицыФормыИмяТаблицыФормы
// Код процедур и функций
#КонецОбласти

#Область ОбработчикиКомандФормы
// Код процедур и функций
#КонецОбласти

#Область ОбработчикиСобытий
// Код процедур и функций
#КонецОбласти

#Область СлужебныеПроцедурыИФункции
Функция Тест()
РегистрыСведений.РегистрСведений1.УстаревшаяПроцедура();
КонецФункции

#КонецОбласти

Процедура НеУстаревшаяПроцедура() Экспорт

КонецПроцедуры

// Устарела. См. НеУстаревшаяПроцедура.
// Процедура - Устаревшая процедура
Процедура УстаревшаяПроцедура() Экспорт

КонецПроцедуры

Функция НеУстаревшаяФункция() Экспорт

КонецФункции

// Устарела. См. НеУстаревшаяФункция.
// Функция - Устаревшая функция
Функция УстаревшаяФункция() Экспорт

ПервыйОбщийМодуль.НеУстаревшаяФункция();
НеУстаревшаяФункция();

КонецФункции

Процедура ВерсионированиеПриЗаписи(Источник, Отказ) Экспорт

КонецПроцедуры

Процедура РегистрацияИзмененийПередУдалением(Источник, Отказ)

КонецПроцедуры
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.11">
<CommonModule uuid="545e2ca7-84d2-4b38-9ede-a97db24b8222">
<Properties>
<Name>ОбщийМодуль3</Name>
<Synonym/>
<Comment/>
<Global>false</Global>
<ClientManagedApplication>false</ClientManagedApplication>
<Server>true</Server>
<ExternalConnection>false</ExternalConnection>
<ClientOrdinaryApplication>false</ClientOrdinaryApplication>
<ServerCall>false</ServerCall>
<Privileged>false</Privileged>
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
</Properties>
</CommonModule>
</MetaDataObject>
Loading

0 comments on commit 73745fb

Please sign in to comment.