Skip to content

Commit 73745fb

Browse files
committed
Реализация правила Обращение к методам привилегированных модулей
добавлена отдельная мини-конфигурация для тестов closes #1870
1 parent 1c83f52 commit 73745fb

File tree

15 files changed

+697
-0
lines changed

15 files changed

+697
-0
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# <Diagnostic name> (PrivilegedModuleMethodCall)
2+
3+
<!-- Блоки выше заполняются автоматически, не трогать -->
4+
## Описание диагностики
5+
<!-- Описание диагностики заполняется вручную. Необходимо понятным языком описать смысл и схему работу -->
6+
При обращении к публичным процедурам и функциям привилегированных общих модулей могут нарушаться ограничения конфигурации по правам и ролям конфигурации, решения 1С.
7+
Необходимо провалидировать подобные обращения для исключения обхода ограничений.
8+
9+
## Примеры
10+
<!-- В данном разделе приводятся примеры, на которые диагностика срабатывает, а также можно привести пример, как можно исправить ситуацию -->
11+
Например, в конфигурации существует привилегированный модуль выполнения заданий с именем `Задания`.
12+
В этом модуле есть публичная функция `Функция ДобавитьЗадание(Знач ИмяМетода, Знач Параметры) Экспорт`.
13+
Какой-то код конфигурации или расширения обращается к этому методу `Задания.ДобавитьЗадание("МетодДляВыполнения", Параметры);`
14+
15+
Необходимо проанализировать код и убедиться в том, что:
16+
- указан правильный метод для выполнения задания - `МетодДляВыполнения`
17+
- метод `МетодДляВыполнения` для выполнения задания не выполняет деструктивных действий
18+
- и не выдает пользователям данные, запрещенные ограничениями конфигурации
19+
20+
## Источники
21+
<!-- Необходимо указывать ссылки на все источники, из которых почерпнута информация для создания диагностики -->
22+
<!-- Примеры источников
23+
24+
* Источник: [Стандарт: Тексты модулей](https://its.1c.ru/db/v8std#content:456:hdoc)
25+
* Полезная информация: [Отказ от использования модальных окон](https://its.1c.ru/db/metod8dev#content:5272:hdoc)
26+
* Источник: [Cognitive complexity, ver. 1.4](https://www.sonarsource.com/docs/CognitiveComplexity.pdf) -->
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# <Diagnostic name> (PrivilegedModuleMethodCall)
2+
3+
<!-- Блоки выше заполняются автоматически, не трогать -->
4+
## Description
5+
<!-- Описание диагностики заполняется вручную. Необходимо понятным языком описать смысл и схему работу -->
6+
7+
## Examples
8+
<!-- В данном разделе приводятся примеры, на которые диагностика срабатывает, а также можно привести пример, как можно исправить ситуацию -->
9+
10+
## Sources
11+
<!-- Необходимо указывать ссылки на все источники, из которых почерпнута информация для создания диагностики -->
12+
<!-- Примеры источников
13+
14+
* Источник: [Стандарт: Тексты модулей](https://its.1c.ru/db/v8std#content:456:hdoc)
15+
* Полезная информация: [Отказ от использования модальных окон](https://its.1c.ru/db/metod8dev#content:5272:hdoc)
16+
* Источник: [Cognitive complexity, ver. 1.4](https://www.sonarsource.com/docs/CognitiveComplexity.pdf) -->
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
* This file is a part of BSL Language Server.
3+
*
4+
* Copyright (c) 2018-2023
5+
* Alexey Sosnoviy <labotamy@gmail.com>, Nikita Fedkin <nixel2007@gmail.com> and contributors
6+
*
7+
* SPDX-License-Identifier: LGPL-3.0-or-later
8+
*
9+
* BSL Language Server is free software; you can redistribute it and/or
10+
* modify it under the terms of the GNU Lesser General Public
11+
* License as published by the Free Software Foundation; either
12+
* version 3.0 of the License, or (at your option) any later version.
13+
*
14+
* BSL Language Server is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17+
* Lesser General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU Lesser General Public
20+
* License along with BSL Language Server.
21+
*/
22+
package com.github._1c_syntax.bsl.languageserver.diagnostics;
23+
24+
import com.github._1c_syntax.bsl.languageserver.context.symbol.ModuleSymbol;
25+
import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticMetadata;
26+
import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticScope;
27+
import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticSeverity;
28+
import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticTag;
29+
import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticType;
30+
import com.github._1c_syntax.bsl.languageserver.references.ReferenceIndex;
31+
import com.github._1c_syntax.bsl.languageserver.references.model.Reference;
32+
import com.github._1c_syntax.bsl.types.ModuleType;
33+
import com.github._1c_syntax.mdclasses.mdo.MDCommonModule;
34+
import lombok.RequiredArgsConstructor;
35+
import org.eclipse.lsp4j.SymbolKind;
36+
37+
import java.util.ArrayList;
38+
import java.util.List;
39+
import java.util.Optional;
40+
41+
@DiagnosticMetadata(
42+
type = DiagnosticType.VULNERABILITY,
43+
severity = DiagnosticSeverity.MAJOR,
44+
minutesToFix = 60,
45+
tags = {
46+
DiagnosticTag.SUSPICIOUS
47+
},
48+
scope = DiagnosticScope.BSL
49+
)
50+
@RequiredArgsConstructor
51+
public class PrivilegedModuleMethodCallDiagnostic extends AbstractDiagnostic {
52+
private final ReferenceIndex referenceIndex;
53+
private List<ModuleSymbol> privilegedModuleSymbols = new ArrayList<>();
54+
55+
private static boolean isReferenceToModules(Reference reference, List<ModuleSymbol> privilegedModuleSymbols) {
56+
return reference.getSourceDefinedSymbol()
57+
.flatMap(sourceDefinedSymbol -> sourceDefinedSymbol.getRootParent(SymbolKind.Module))
58+
.filter(ModuleSymbol.class::isInstance)
59+
.map(ModuleSymbol.class::cast)
60+
.filter(privilegedModuleSymbols::contains)
61+
.isPresent();
62+
}
63+
64+
@Override
65+
protected void check() {
66+
if (privilegedModuleSymbols.isEmpty()){
67+
privilegedModuleSymbols = getPrivilegedModuleSymbols();
68+
}
69+
if (privilegedModuleSymbols.isEmpty()){
70+
return;
71+
}
72+
73+
referenceIndex.getReferencesFrom(documentContext.getUri(), SymbolKind.Method).stream()
74+
.filter(reference -> isReferenceToModules(reference, privilegedModuleSymbols))
75+
.forEach(this::fireIssue);
76+
}
77+
78+
private List<ModuleSymbol> getPrivilegedModuleSymbols() {
79+
return documentContext.getServerContext().getConfiguration().getCommonModules()
80+
.values().stream()
81+
.filter(MDCommonModule::isPrivileged)
82+
.flatMap(mdCommonModule -> getPrivilegedModuleSymbol(mdCommonModule).stream())
83+
.toList();
84+
}
85+
86+
private Optional<ModuleSymbol> getPrivilegedModuleSymbol(MDCommonModule mdCommonModule) {
87+
return documentContext.getServerContext().getDocument(
88+
mdCommonModule.getMdoReference().getMdoRef(), ModuleType.CommonModule)
89+
.map(documentContext1 -> documentContext1.getSymbolTree().getModule());
90+
}
91+
92+
private void fireIssue(Reference reference) {
93+
diagnosticStorage.addDiagnostic(reference.getSelectionRange(),
94+
info.getMessage(reference.getSymbol().getName()));
95+
}
96+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
diagnosticMessage=Check the %s method access of the privileged module
2+
diagnosticName=Accessing privileged module methods
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
diagnosticMessage=Проверьте обращение к методу %s привилегированного модуля
2+
diagnosticName=Обращение к методам привилегированных модулей
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* This file is a part of BSL Language Server.
3+
*
4+
* Copyright (c) 2018-2023
5+
* Alexey Sosnoviy <labotamy@gmail.com>, Nikita Fedkin <nixel2007@gmail.com> and contributors
6+
*
7+
* SPDX-License-Identifier: LGPL-3.0-or-later
8+
*
9+
* BSL Language Server is free software; you can redistribute it and/or
10+
* modify it under the terms of the GNU Lesser General Public
11+
* License as published by the Free Software Foundation; either
12+
* version 3.0 of the License, or (at your option) any later version.
13+
*
14+
* BSL Language Server is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17+
* Lesser General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU Lesser General Public
20+
* License along with BSL Language Server.
21+
*/
22+
package com.github._1c_syntax.bsl.languageserver.diagnostics;
23+
24+
import org.eclipse.lsp4j.Diagnostic;
25+
import org.junit.jupiter.api.Test;
26+
27+
import java.util.List;
28+
29+
import static com.github._1c_syntax.bsl.languageserver.util.Assertions.assertThat;
30+
31+
class PrivilegedModuleMethodCallDiagnosticTest extends AbstractDiagnosticTest<PrivilegedModuleMethodCallDiagnostic> {
32+
private static final String PATH_TO_METADATA = "src/test/resources/metadata/privilegedModules";
33+
34+
PrivilegedModuleMethodCallDiagnosticTest() {
35+
super(PrivilegedModuleMethodCallDiagnostic.class);
36+
}
37+
38+
@Test
39+
void test() {
40+
initServerContext(PATH_TO_METADATA);
41+
42+
List<Diagnostic> diagnostics = getDiagnostics();
43+
44+
assertThat(diagnostics).hasSize(2);
45+
assertThat(diagnostics, true)
46+
.hasMessageOnRange("Проверьте обращение к методу ПубличнаяФункция привилегированного модуля", 3, 40, 56)
47+
.hasMessageOnRange("Проверьте обращение к методу ПубличнаяПроцедура привилегированного модуля", 4, 29, 47);
48+
}
49+
50+
@Test
51+
void testWithoutMetadata() {
52+
53+
List<Diagnostic> diagnostics = getDiagnostics();
54+
assertThat(diagnostics).isEmpty();
55+
}
56+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#Область ПрограммныйИнтерфейс
2+
3+
Функция Тест1()
4+
Значение = ПривилегированныйМодуль1.ПубличнаяФункция(); // ошибка
5+
ПривилегированныйМодуль1.ПубличнаяПроцедура(); // ошибка
6+
КонецФункции
7+
8+
Процедура Тест2()
9+
Значение = ПривилегированныйМодуль1.ПриватнаяФункция(); // не ошибка в данном правиле
10+
ПривилегированныйМодуль1.ПриватнаяПроцедура(); // не ошибка в данном правиле
11+
КонецПроцедуры
12+
13+
#КонецОбласти
14+
15+
#Область СлужебныеПроцедурыИФункции
16+
17+
#КонецОбласти
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<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">
3+
<CommonModule uuid="8bec7488-90ab-484a-bdc9-ce1584d95925">
4+
<Properties>
5+
<Name>ОбщийМодуль2</Name>
6+
<Synonym/>
7+
<Comment/>
8+
<Global>false</Global>
9+
<ClientManagedApplication>false</ClientManagedApplication>
10+
<Server>true</Server>
11+
<ExternalConnection>false</ExternalConnection>
12+
<ClientOrdinaryApplication>false</ClientOrdinaryApplication>
13+
<ServerCall>false</ServerCall>
14+
<Privileged>false</Privileged>
15+
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
16+
</Properties>
17+
</CommonModule>
18+
</MetaDataObject>
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
2+
/////Описание
3+
/////
4+
/////
5+
6+
#Область ОписаниеПеременных
7+
8+
9+
10+
11+
#КонецОбласти
12+
13+
#Область ПрограммныйИнтерфейс
14+
// Код процедур и функций
15+
#КонецОбласти
16+
17+
#Область СлужебныйПрограммныйИнтерфейс
18+
// Код процедур и функций
19+
#КонецОбласти
20+
21+
#Область СлужебныеПроцедурыИФункции
22+
// Код процедур и функций
23+
#КонецОбласти
24+
25+
26+
#Region EventHandlers
27+
// Enter code here.
28+
#EndRegion
29+
30+
#Region Internal
31+
// Enter code here.
32+
#EndRegion
33+
34+
#Область ОбработчикиСобытийФормы
35+
// Код процедур и функций
36+
#КонецОбласти
37+
38+
#Область ОбработчикиСобытийЭлементовШапкиФормы
39+
// Код процедур и функций
40+
#КонецОбласти
41+
42+
#Область ОбработчикиСобытийЭлементовТаблицыФормыИмяТаблицыФормы
43+
// Код процедур и функций
44+
#КонецОбласти
45+
46+
#Область ОбработчикиКомандФормы
47+
// Код процедур и функций
48+
#КонецОбласти
49+
50+
#Область ОбработчикиСобытий
51+
// Код процедур и функций
52+
#КонецОбласти
53+
54+
#Область СлужебныеПроцедурыИФункции
55+
Функция Тест()
56+
РегистрыСведений.РегистрСведений1.УстаревшаяПроцедура();
57+
КонецФункции
58+
59+
#КонецОбласти
60+
61+
Процедура НеУстаревшаяПроцедура() Экспорт
62+
63+
КонецПроцедуры
64+
65+
// Устарела. См. НеУстаревшаяПроцедура.
66+
// Процедура - Устаревшая процедура
67+
Процедура УстаревшаяПроцедура() Экспорт
68+
69+
КонецПроцедуры
70+
71+
Функция НеУстаревшаяФункция() Экспорт
72+
73+
КонецФункции
74+
75+
// Устарела. См. НеУстаревшаяФункция.
76+
// Функция - Устаревшая функция
77+
Функция УстаревшаяФункция() Экспорт
78+
79+
ПервыйОбщийМодуль.НеУстаревшаяФункция();
80+
НеУстаревшаяФункция();
81+
82+
КонецФункции
83+
84+
Процедура ВерсионированиеПриЗаписи(Источник, Отказ) Экспорт
85+
86+
КонецПроцедуры
87+
88+
Процедура РегистрацияИзмененийПередУдалением(Источник, Отказ)
89+
90+
КонецПроцедуры
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<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">
3+
<CommonModule uuid="545e2ca7-84d2-4b38-9ede-a97db24b8222">
4+
<Properties>
5+
<Name>ОбщийМодуль3</Name>
6+
<Synonym/>
7+
<Comment/>
8+
<Global>false</Global>
9+
<ClientManagedApplication>false</ClientManagedApplication>
10+
<Server>true</Server>
11+
<ExternalConnection>false</ExternalConnection>
12+
<ClientOrdinaryApplication>false</ClientOrdinaryApplication>
13+
<ServerCall>false</ServerCall>
14+
<Privileged>false</Privileged>
15+
<ReturnValuesReuse>DontUse</ReturnValuesReuse>
16+
</Properties>
17+
</CommonModule>
18+
</MetaDataObject>

0 commit comments

Comments
 (0)