diff --git a/package.json b/package.json
index 5f0a3db271..84f56bd81d 100644
--- a/package.json
+++ b/package.json
@@ -37,6 +37,7 @@
"@ngx-translate/http-loader": "^2.0.0",
"chart.js": "2.7.0",
"core-js": "^2.4.1",
+ "ip-address": "^5.8.9",
"jasmine": "^2.8.0",
"jasmine-marbles": "^0.2.0",
"lodash": "^4.17.4",
@@ -48,6 +49,7 @@
"reflect-metadata": "^0.1.10",
"rxjs": "^5.5.2",
"showdown": "^1.8.4",
+ "sprintf-js": "^1.1.1",
"uuid": "^3.1.0",
"web-animations-js": "2.3.1",
"zone.js": "0.8.12"
diff --git a/src/app/security-group/sg-rules/sg-rule.component.html b/src/app/security-group/sg-rules/sg-rule.component.html
index 07d79c8ed8..d033b0443f 100644
--- a/src/app/security-group/sg-rules/sg-rule.component.html
+++ b/src/app/security-group/sg-rules/sg-rule.component.html
@@ -3,29 +3,39 @@
diff --git a/src/app/security-group/sg-rules/sg-rule.component.ts b/src/app/security-group/sg-rules/sg-rule.component.ts
index 460907377f..ab5652745f 100644
--- a/src/app/security-group/sg-rules/sg-rule.component.ts
+++ b/src/app/security-group/sg-rules/sg-rule.component.ts
@@ -5,12 +5,15 @@ import {
Input,
Output
} from '@angular/core';
+import { Utils } from '../../shared/services/utils/utils.service';
import { NetworkProtocol, NetworkRule } from '../network-rule.model';
import { TranslateService } from '@ngx-translate/core';
import {
GetICMPCodeTranslationToken,
- GetICMPTypeTranslationToken
+ GetICMPTypeTranslationToken, GetICMPV6CodeTranslationToken,
+ GetICMPV6TypeTranslationToken
} from '../../shared/icmp/icmp-types';
+import { IPVersion, NetworkRuleType } from '../sg.model';
@Component({
selector: 'cs-security-group-rule',
@@ -25,6 +28,7 @@ export class SgRuleComponent {
public deleting = false;
public NetworkProtocols = NetworkProtocol;
+ public NetworkRuleTypes = NetworkRuleType;
public get typeTranslationToken(): string {
const typeTranslations = {
@@ -46,18 +50,27 @@ export class SgRuleComponent {
}
public get icmpTypeTranslationToken(): string {
- return GetICMPTypeTranslationToken(this.item.icmpType);
+ return Utils.cidrType(this.item.CIDR) === IPVersion.ipv4
+ ? GetICMPTypeTranslationToken(this.item.icmpType)
+ : GetICMPV6TypeTranslationToken(this.item.icmpType);
}
public get icmpCodeTranslationToken(): string {
- return GetICMPCodeTranslationToken(this.item.icmpType, this.item.icmpCode);
+ return Utils.cidrType(this.item.CIDR) === IPVersion.ipv4
+ ? GetICMPCodeTranslationToken(this.item.icmpType, this.item.icmpCode)
+ : GetICMPV6CodeTranslationToken(this.item.icmpType, this.item.icmpCode);
}
public get ruleParams(): Object {
+ const ipVersion = Utils.cidrType(this.item.CIDR) === IPVersion.ipv4
+ ? IPVersion.ipv4
+ : IPVersion.ipv6;
+
const params = {
type: this.translateService.instant(this.typeTranslationToken),
protocol: this.translateService.instant(this.protocolTranslationToken),
cidr: this.item.CIDR,
+ ipVersion
};
let ruleParams;
diff --git a/src/app/security-group/sg-rules/sg-rules.component.html b/src/app/security-group/sg-rules/sg-rules.component.html
index fe6a120e13..7cc0b7c344 100644
--- a/src/app/security-group/sg-rules/sg-rules.component.html
+++ b/src/app/security-group/sg-rules/sg-rules.component.html
@@ -45,12 +45,13 @@
name="cidr"
type="text"
[(ngModel)]="cidr"
- pattern="^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$"
+ (change)="onCidrChange()"
+ [errorStateMatcher]="cidrMatcher"
+ [placeholder]="'SECURITY_GROUP_PAGE.RULES.ENTER_CIDR' | translate"
required
- (click)="onCidrClick()"
#cidrField="ngModel"
>
-
+
{{ 'SECURITY_GROUP_PAGE.RULES.ENTER_VALID_CIDR' | translate }}
@@ -62,7 +63,7 @@
+
+
+
+ {{ t }}
+
+
+
= require(
+ '../../../testutils/mocks/model-services/fixtures/securityGroupTemplates.json');
+
@Injectable()
class MockRouter {
public navigate(route: any): Promise {
@@ -41,6 +45,66 @@ describe('Security group firewall rules component', () => {
virtualMachinesCount: 0,
virtualMachineIds: []
});
+ const mockSecurityGroupWithRules = new SecurityGroup({
+ id: '9d1f0e3b-82a7-4528-b02e-70c4f9eff4b0',
+ name: 'test',
+ description: '',
+ account: 'develop',
+ domain: 'ROOT',
+ ingressRules: [
+ {
+ ruleId: 'ed4a91f5-35f2-48a3-b706-6a00dba50708',
+ protocol: 'icmp',
+ icmpType: 3,
+ icmpCode: 2,
+ CIDR: '2001:DB8::/128',
+ tags: []
+ },
+ {
+ ruleId: '293a8e35-7c26-4216-851e-c87a46c9620f',
+ protocol: 'tcp',
+ startPort: 0,
+ endPort: 65535,
+ CIDR: '2001:DB8::/128',
+ tags: []
+ },
+ {
+ ruleId: 'af34ea6c-dd50-4cab-9f5e-ca4e454e59d3',
+ protocol: 'icmp',
+ icmpType: 2,
+ icmpCode: 0,
+ CIDR: '2001:DB8::/128',
+ tags: []
+ },
+ {
+ ruleId: '41ce53d6-5274-49b0-a2e9-7b0ebc87c89a',
+ protocol: 'icmp',
+ icmpType: 132,
+ icmpCode: 0,
+ CIDR: '2001:DB8::/128',
+ tags: []
+ },
+ {
+ ruleId: '02990ed4-827f-49a1-bb27-4ea6d565c1fd',
+ protocol: 'icmp',
+ icmpType: 4,
+ icmpCode: 1,
+ CIDR: '2001:DB8::/128',
+ tags: []
+ },
+ {
+ ruleId: '787ee1c9-ec5f-4612-9894-1080acec515e',
+ protocol: 'icmp',
+ icmpType: 0,
+ icmpCode: 0,
+ CIDR: '0.0.0.0/0',
+ tags: []
+ }
+ ],
+ tags: [],
+ virtualMachinesCount: 0,
+ virtualMachineIds: []
+ });
class SecurityGroupServiceMock {
public getPredefinedTemplates(): Array {
@@ -92,18 +156,62 @@ describe('Security group firewall rules component', () => {
});
}));
- it('filter lists of ICMP types and codes', () => {
- const filteredTypes = comp.filterTypes('-1');
+ it('filter lists of ICMP types and codes', async(() => {
+ comp.cidr = '::/128';
+ const filteredTypes = comp.filterTypes('255');
expect(filteredTypes.length).toEqual(1);
comp.selectedType = filteredTypes[0].type.toString();
comp.setIcmpTypes(filteredTypes);
- const filteredCodes = comp.filterCodes('-1');
+ const filteredCodes = comp.filterCodes('255');
expect(filteredCodes.length).toEqual(1);
comp.selectedCode = filteredCodes[0].toString();
comp.setIcmpCodes(comp.selectedCode);
- expect(comp.icmpType).toEqual(-1);
- expect(comp.icmpCode).toEqual(-1);
+ expect(comp.icmpType).toEqual(255);
+ expect(comp.icmpCode).toEqual(0);
+ }));
+
+ it('filter network rules by IP version, type or protocol', () => {
+ comp.securityGroup = mockSecurityGroupWithRules;
+ comp.ngOnChanges();
+
+ expect(comp.visibleRules.length).toEqual(6);
+
+ comp.selectedIPVersion = [IPVersion.ipv6];
+ comp.filter();
+ expect(comp.visibleRules.length).toEqual(5);
+
+ comp.selectedType = [NetworkRuleType.Ingress];
+ comp.filter();
+ expect(comp.visibleRules.length).toEqual(5);
+ comp.selectedIPVersion = [];
+ comp.selectedType = [];
+ comp.filter();
+ expect(comp.visibleRules.length).toEqual(6);
+
+ comp.selectedProtocols = [NetworkProtocol.ICMP];
+ comp.filter();
+ expect(comp.visibleRules.length).toEqual(5);
});
+
+ it('should filter predefined templates', async(() => {
+ comp.securityGroup = securityGroupTemplates[0];
+ expect(comp.isPredefinedTemplate).toBeTruthy();
+ comp.securityGroup = mockSecurityGroupWithRules;
+ expect(comp.isPredefinedTemplate).toBeFalsy();
+ }));
+
+ it('should select types by CIDR IP version', async(() => {
+ comp.cidr = '2001:DB8::/128';
+ comp.onCidrChange();
+ expect(comp.icmpTypes).toEqual(ICMPv6Types);
+ }));
+
+ it('should change view or edit mode', async(() => {
+ comp.editMode = false;
+ comp.securityGroup = securityGroupTemplates[0];
+ comp.confirmChangeMode();
+ expect(comp.editMode).toBeTruthy();
+ }));
});
diff --git a/src/app/security-group/sg-rules/sg-rules.component.ts b/src/app/security-group/sg-rules/sg-rules.component.ts
index 6af3f17431..4e1cbf164a 100644
--- a/src/app/security-group/sg-rules/sg-rules.component.ts
+++ b/src/app/security-group/sg-rules/sg-rules.component.ts
@@ -6,22 +6,41 @@ import {
Output,
ViewChild
} from '@angular/core';
-import { NgForm } from '@angular/forms';
+import { FormControl, FormGroupDirective, NgForm } from '@angular/forms';
+import { ErrorStateMatcher } from '@angular/material';
import { TranslateService } from '@ngx-translate/core';
import {
GetICMPCodeTranslationToken,
GetICMPTypeTranslationToken,
+ GetICMPV6CodeTranslationToken,
+ GetICMPV6TypeTranslationToken,
ICMPType,
- ICMPtypes
+ ICMPtypes,
+ ICMPv6Types
} from '../../shared/icmp/icmp-types';
import { NotificationService } from '../../shared/services/notification.service';
+import { Utils } from '../../shared/services/utils/utils.service';
import { NetworkRuleService } from '../services/network-rule.service';
-import { NetworkRuleType, SecurityGroup, SecurityGroupType } from '../sg.model';
+import {
+ getType,
+ IPVersion, NetworkRuleType, SecurityGroup,
+ SecurityGroupType
+} from '../sg.model';
import { NetworkProtocol, NetworkRule } from '../network-rule.model';
import { DialogService } from '../../dialog/dialog-service/dialog.service';
import { Router } from '@angular/router';
import { SgRuleComponent } from './sg-rule.component';
+export class CidrStateMatcher implements ErrorStateMatcher {
+ isErrorState(
+ control: FormControl | null,
+ form: FormGroupDirective | NgForm | null
+ ): boolean {
+ const invalidCidr = control.value && !Utils.cidrIsValid(control.value);
+
+ return control && (control.dirty || control.touched) && invalidCidr;
+ }
+}
@Component({
selector: 'cs-security-group-rules',
@@ -29,7 +48,7 @@ import { SgRuleComponent } from './sg-rule.component';
styleUrls: ['sg-rules.component.scss']
})
export class SgRulesComponent implements OnChanges {
- @Input() public securityGroup: any;
+ @Input() public securityGroup: SecurityGroup;
@Input() public editMode = false;
@Input() public vmId: string;
@Output() public onCloseDialog = new EventEmitter();
@@ -38,6 +57,7 @@ export class SgRulesComponent implements OnChanges {
@ViewChild('rulesForm') public rulesForm: NgForm;
public selectedType = '';
public selectedCode = '';
+ public selectedIPVersion: string[] = [];
public selectedTypes: string[] = [];
public selectedProtocols: string[] = [];
@@ -45,17 +65,18 @@ export class SgRulesComponent implements OnChanges {
public protocol: NetworkProtocol;
public startPort: number;
public icmpType: number;
- public icmpTypes: ICMPType[] = ICMPtypes;
public icmpCode: number;
public icmpCodes: number[];
public endPort: number;
public cidr: string;
- public ingressRules: NetworkRule[] = [];
- public egressRules: NetworkRule[] = [];
+ public cidrMatcher = new CidrStateMatcher();
+ public ingressRules = [];
+ public egressRules = [];
public visibleRules: NetworkRule[] = [];
public adding: boolean;
+ public IPversions = [IPVersion.ipv4, IPVersion.ipv6];
public NetworkProtocols = NetworkProtocol;
public NetworkRuleTypes = NetworkRuleType;
@@ -90,8 +111,23 @@ export class SgRulesComponent implements OnChanges {
{ value: NetworkProtocol.ICMP, text: 'SECURITY_GROUP_PAGE.RULES.ICMP' }
];
- public getIcmpTypeTranslationToken = GetICMPTypeTranslationToken;
- public getIcmpCodeTranslationToken = GetICMPCodeTranslationToken;
+ private _icmpTypes: ICMPType[];
+
+ public get isPredefinedTemplate(): boolean {
+ return this.securityGroup && getType(this.securityGroup) === SecurityGroupType.PredefinedTemplate;
+ }
+
+ public get icmpTypes(): ICMPType[] {
+ return this._icmpTypes ? this._icmpTypes : this.typesByCIDR;
+ }
+
+ public isCidrValid(input: string) {
+ const test1 = '0.0.0.0/0';
+ const test2 = '2001:DB8::/128';
+ console.log(Utils.cidrType(test1), Utils.cidrType(test2));
+
+ return input && Utils.cidrIsValid(input);
+ }
constructor(
private networkRuleService: NetworkRuleService,
@@ -100,7 +136,6 @@ export class SgRulesComponent implements OnChanges {
private dialogService: DialogService,
private router: Router
) {
- this.cidr = '0.0.0.0/0';
this.protocol = NetworkProtocol.TCP;
this.type = NetworkRuleType.Ingress;
@@ -119,10 +154,6 @@ export class SgRulesComponent implements OnChanges {
this.update();
}
- public get isPredefinedTemplate(): boolean {
- return this.securityGroup && this.securityGroup.type === SecurityGroupType.PredefinedTemplate;
- }
-
public addRule(e: Event): void {
e.stopPropagation();
@@ -187,18 +218,12 @@ export class SgRulesComponent implements OnChanges {
});
}
- public onCidrClick(): void {
- if (!this.cidr) {
- this.cidr = '0.0.0.0/0';
- }
- }
-
public setIcmpTypes(value: ICMPType[]) {
- this.icmpTypes = value;
+ this._icmpTypes = value;
if (+this.selectedType <= 255 && +this.selectedType >= -1) {
this.icmpType = +this.selectedType;
- const type = ICMPtypes.find(_ => {
+ const type = this.typesByCIDR.find(_ => {
return _.type === this.icmpType;
});
this.selectedCode = '';
@@ -214,22 +239,39 @@ export class SgRulesComponent implements OnChanges {
}
}
+ public get typesByCIDR(): ICMPType[] {
+ return this.cidrIpVersion === IPVersion.ipv6 ? ICMPv6Types : ICMPtypes;
+ }
+
+ public get IPVersion() {
+ return IPVersion;
+ }
+
+ public get cidrIpVersion(): IPVersion {
+ return this.cidr && Utils.cidrType(this.cidr) === IPVersion.ipv6
+ ? IPVersion.ipv6
+ : IPVersion.ipv4;
+ }
+
+ public onCidrChange() {
+ this._icmpTypes = this.typesByCIDR;
+ }
+
public filter(): void {
if (!this.securityGroup) {
return;
}
const filteredEgressRules = this.filterRules(this.egressRules);
const filteredIngressRules = this.filterRules(this.ingressRules);
-
this.visibleRules = [...filteredIngressRules, ...filteredEgressRules];
}
public filterTypes(val: number | string) {
const filterValue = val.toString().toLowerCase();
- return !!val ? ICMPtypes.filter(_ => _.type.toString() === filterValue ||
+ return !!val ? this.typesByCIDR.filter(_ => _.type.toString() === filterValue ||
this.translateService.instant(this.getIcmpTypeTranslationToken(_.type))
.toLowerCase()
- .indexOf(filterValue) !== -1) : ICMPtypes;
+ .indexOf(filterValue) !== -1) : this.typesByCIDR;
}
public filterCodes(val: number | string) {
@@ -238,12 +280,12 @@ export class SgRulesComponent implements OnChanges {
_.toString().indexOf(filterValue) !== -1 ||
this.translateService.instant(this.getIcmpCodeTranslationToken(this.icmpType, _))
.toLowerCase()
- .indexOf(filterValue) !== -1) : ICMPtypes.find(
+ .indexOf(filterValue) !== -1) : this.typesByCIDR.find(
x => x.type === this.icmpType).codes;
}
public confirmChangeMode() {
- if (!this.editMode && this.securityGroup.type === SecurityGroupType.Shared) {
+ if (!this.editMode && getType(this.securityGroup) === SecurityGroupType.Shared) {
this.dialogService.confirm({
message: !this.vmId
? 'DIALOG_MESSAGES.SECURITY_GROUPS.CONFIRM_EDIT'
@@ -300,18 +342,40 @@ export class SgRulesComponent implements OnChanges {
private resetFilters() {
this.selectedTypes = [];
this.selectedProtocols = [];
+ this.selectedIPVersion = [];
this.filter();
}
private filterRules(rules: NetworkRule[]) {
return rules.filter((rule: NetworkRule) => {
- return (!this.selectedProtocols.length
- || this.selectedProtocols.find(protocol => protocol === rule.protocol))
- && (!this.selectedTypes.length
- || this.selectedTypes.find(type => rule.type === type));
+ const filterByIPversion = (item: NetworkRule) => {
+ const ruleIPversion = item.CIDR && Utils.cidrType(item.CIDR) === IPVersion.ipv6
+ ? IPVersion.ipv6
+ : IPVersion.ipv4;
+ return !this.selectedIPVersion.length
+ || this.selectedIPVersion.find(version => version === ruleIPversion);
+ };
+ const filterByProtocol = (item: NetworkRule) => !this.selectedProtocols.length
+ || this.selectedProtocols.find(protocol => protocol === item.protocol);
+ const filterByTypes = (item: NetworkRule) => !this.selectedTypes.length
+ || this.selectedTypes.find(type => item.type === type);
+
+ return filterByTypes(rule) && filterByIPversion(rule) && filterByProtocol(rule);
});
}
+ public getIcmpTypeTranslationToken(type: number) {
+ return this.cidrIpVersion === IPVersion.ipv6
+ ? GetICMPV6TypeTranslationToken(type)
+ : GetICMPTypeTranslationToken(type);
+ }
+
+ public getIcmpCodeTranslationToken(type: number, code: number) {
+ return this.cidrIpVersion === IPVersion.ipv6
+ ? GetICMPV6CodeTranslationToken(type, code)
+ : GetICMPCodeTranslationToken(type, code);
+ }
+
private emitChanges() {
const updatedSecurityGroup = new SecurityGroup(this.securityGroup);
updatedSecurityGroup.ingressRules = this.ingressRules;
diff --git a/src/app/security-group/sg.model.ts b/src/app/security-group/sg.model.ts
index b06bace1b2..31ccfc3b98 100644
--- a/src/app/security-group/sg.model.ts
+++ b/src/app/security-group/sg.model.ts
@@ -18,6 +18,11 @@ export enum NetworkRuleType {
Egress = 'Egress'
}
+export enum IPVersion {
+ ipv4 = 'ipv4',
+ ipv6 = 'ipv6'
+}
+
@FieldMapper({
ingressrule: 'ingressRules',
egressrule: 'egressRules',
@@ -97,5 +102,5 @@ export const isCustomTemplate = (securityGroup: SecurityGroup) => {
export const isPrivate = (securityGroup: SecurityGroup) => {
const typeTag = securityGroup.tags.find(tag => tag.key === SecurityGroupTagKeys.type);
- return typeTag && typeTag.value === SecurityGroupType.Private
+ return typeTag && typeTag.value === SecurityGroupType.Private;
};
diff --git a/src/app/shared/icmp/icmp-types.ts b/src/app/shared/icmp/icmp-types.ts
index 8b3f445e90..b00622879b 100644
--- a/src/app/shared/icmp/icmp-types.ts
+++ b/src/app/shared/icmp/icmp-types.ts
@@ -5,113 +5,82 @@ export interface ICMPType {
}
export const ICMPtypes = [
- {
- type: -1,
- codes: [-1]
- },
- {
- type: 0,
- codes: [0]
- },
- {
- type: 3,
- codes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
- },
- {
- type: 4,
- codes: [0]
- },
- {
- type: 5,
- codes: [0, 1, 2, 3]
- }, {
- type: 6,
- codes: [0]
- },
- {
- type: 8,
- codes: [0]
- },
- {
- type: 9,
- codes: [0]
- },
- {
- type: 10,
- codes: [0]
- },
- {
- type: 11,
- codes: [0, 1]
- },
- {
- type: 12,
- codes: [0, 1, 2]
- },
- {
- type: 13,
- codes: [0]
- },
- {
- type: 14,
- codes: [0]
- },
- {
- type: 15,
- codes: [0]
- },
- {
- type: 16,
- codes: [0]
- },
- {
- type: 17,
- codes: [0]
- },
- {
- type: 18,
- codes: [0]
- },
- {
- type: 30,
- codes: [0]
- }, {
- type: 31,
- codes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
- }, {
- type: 32,
- codes: [0]
- }, {
- type: 33,
- codes: [0]
- }, {
- type: 34,
- codes: [0]
- }, {
- type: 35,
- codes: [0]
- }, {
- type: 36,
- codes: [0]
- }, {
- type: 37,
- codes: [0]
- }, {
- type: 38,
- codes: [0]
- }, {
- type: 39,
- codes: [0]
- }, {
- type: 40,
- codes: [0, 1, 2, 3, 4, 5]
- },
+ { type: -1, codes: [-1] },
+ { type: 0, codes: [0] },
+ { type: 3, codes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] },
+ { type: 4, codes: [0] },
+ { type: 5, codes: [0, 1, 2, 3] },
+ { type: 6, codes: [0] },
+ { type: 8, codes: [0] },
+ { type: 9, codes: [0] },
+ { type: 10, codes: [0] },
+ { type: 11, codes: [0, 1] },
+ { type: 12, codes: [0, 1, 2] },
+ { type: 13, codes: [0] },
+ { type: 14, codes: [0] },
+ { type: 15, codes: [0] },
+ { type: 16, codes: [0] },
+ { type: 17, codes: [0] },
+ { type: 18, codes: [0] },
+ { type: 30, codes: [0] },
+ { type: 31, codes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] },
+ { type: 32, codes: [0] },
+ { type: 33, codes: [0] },
+ { type: 34, codes: [0] },
+ { type: 35, codes: [0] },
+ { type: 36, codes: [0] },
+ { type: 37, codes: [0] },
+ { type: 38, codes: [0] },
+ { type: 39, codes: [0] },
+ { type: 40, codes: [0, 1, 2, 3, 4, 5] },
];
-export const GetICMPTypeTranslationToken = (type) => {
+export const ICMPv6Types = [
+ { type: 1, codes: [0, 1, 2, 3, 4, 5, 6] },
+ { type: 2, codes: [0] },
+ { type: 3, codes: [0, 1] },
+ { type: 4, codes: [0, 1, 2] },
+ { type: 100, codes: [0] },
+ { type: 101, codes: [0] },
+ { type: 127, codes: [0] },
+ { type: 128, codes: [0] },
+ { type: 129, codes: [0] },
+ { type: 130, codes: [0] },
+ { type: 131, codes: [0] },
+ { type: 132, codes: [0] },
+ { type: 133, codes: [0] },
+ { type: 134, codes: [0] },
+ { type: 135, codes: [0] },
+ { type: 136, codes: [0] },
+ { type: 137, codes: [0] },
+ { type: 138, codes: [0, 1, 255] },
+ { type: 139, codes: [0, 1, 2] },
+ { type: 140, codes: [0, 1, 2] },
+ { type: 141, codes: [0] },
+ { type: 142, codes: [0] },
+ { type: 144, codes: [0] },
+ { type: 145, codes: [0] },
+ { type: 146, codes: [0] },
+ { type: 147, codes: [0] },
+ { type: 160, codes: [0] },
+ { type: 161, codes: [0, 1, 2, 3, 4] },
+ { type: 200, codes: [0] },
+ { type: 201, codes: [0] },
+ { type: 255, codes: [0] }
+];
+
+export const GetICMPTypeTranslationToken = (type: number) => {
return `SECURITY_GROUP_PAGE.ICMP_TYPES.${type}.description`;
};
-export const GetICMPCodeTranslationToken = (type, code) => {
+export const GetICMPCodeTranslationToken = (type: number, code: number) => {
return `SECURITY_GROUP_PAGE.ICMP_TYPES.${type}.codes.${code}`;
};
+
+export const GetICMPV6TypeTranslationToken = (type: number) => {
+ return `SECURITY_GROUP_PAGE.ICMP_V6_TYPES.${type}.description`;
+};
+
+export const GetICMPV6CodeTranslationToken = (type: number, code: number) => {
+ return `SECURITY_GROUP_PAGE.ICMP_V6_TYPES.${type}.codes.${code}`;
+};
diff --git a/src/app/shared/services/utils/utils.service.ts b/src/app/shared/services/utils/utils.service.ts
index 1c6c6de8c1..00df79b645 100644
--- a/src/app/shared/services/utils/utils.service.ts
+++ b/src/app/shared/services/utils/utils.service.ts
@@ -1,11 +1,8 @@
-import * as uuid from 'uuid';
-import {
- Params,
- RouterState,
- RouterStateSnapshot
-} from '@angular/router';
+import { Params, RouterState, RouterStateSnapshot } from '@angular/router';
import { RouterStateSerializer } from '@ngrx/router-store';
-
+import { IPVersion } from '../../../security-group/sg.model';
+import * as uuid from 'uuid';
+import * as ipaddr from 'ip-address';
export class Utils {
public static getUniqueId(): string {
@@ -82,7 +79,7 @@ export class Utils {
const g = parseInt(hex.substring(2, 4), 16);
const b = parseInt(hex.substring(4, 6), 16);
- const darkness = 1 - ( 0.299 * r + 0.587 * g + 0.114 * b) / 255;
+ const darkness = 1 - (0.299 * r + 0.587 * g + 0.114 * b) / 255;
return darkness > 0.5;
}
@@ -90,6 +87,18 @@ export class Utils {
public static sortByName = (a, b) => {
return a.name && a.name.localeCompare(b.name);
};
+
+ public static cidrIsValid(range: string): boolean {
+ const ipAddressType = range.match(':') ? ipaddr.Address6 : ipaddr.Address4;
+ const cidr = new ipAddressType(range);
+ return cidr.isValid();
+ }
+
+ public static cidrType(range: string): IPVersion {
+ const ipAddressType = range.match(':') ? ipaddr.Address6 : ipaddr.Address4;
+ const cidr = new ipAddressType(range);
+ return cidr.isValid() && (cidr.v4 ? IPVersion.ipv4 : IPVersion.ipv6);
+ }
}
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 883dd2a290..d3a48948ab 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -812,21 +812,33 @@
"ENTER_VALID_PORT": "Enter a valid port",
"ENTER_VALID_TYPE": "Enter a valid type",
"ENTER_VALID_CODE": "Enter a valid code",
+ "ENTER_CIDR": "CIDR v4/v6",
"ENTER_VALID_CIDR": "Enter a valid CIDR",
"FAILED_TO_ADD_RULE": "Failed to add the rule",
"FAILED_TO_REMOVE_RULE": "Failed to remove the rule",
+ "SELECT_IP_VERSION": "Select IP version",
"SELECT_TYPE": "Select types",
"SELECT_PROTOCOL": "Select protocols",
- "DEFAULT_RULE": "{{ type }} {{ protocol }} traffic to ip {{ cidr }} to port {{ startPort }}",
- "DEFAULT_RULE_PORT_RANGE": "{{ type }} {{ protocol }} traffic to ip {{ cidr }} to port range {{ startPort }}-{{ endPort }}",
- "DEFAULT_ICMP_RULE": "{{ type }} {{ protocol }} traffic to ip {{ cidr }} of ICMP type {{ icmpTypeText }} [{{ icmpType }}] and ICMP code {{ icmpCodeText }} [{{ icmpCode }}]",
- "NO_TEXT_ICMP_RULE": "{{ type }} {{ protocol }} traffic to ip {{ cidr }} of ICMP type {{ icmpType }} and ICMP code {{ icmpCode }}",
- "NO_CODE_ICMP_RULE": "{{ type }} {{ protocol }} traffic to ip {{ cidr }} of ICMP type {{ icmpTypeText }} [{{ icmpType }}] and ICMP code {{ icmpCode }}",
- "DEFAULT_RULE_NOMARKUP": "{{ type }} {{ protocol }} traffic to ip {{ cidr }} to port {{ startPort }}",
- "DEFAULT_RULE_PORT_RANGE_NOMARKUP": "{{ type }} {{ protocol }} traffic to ip {{ cidr }} to port range {{ startPort }}-{{ endPort }}",
- "DEFAULT_ICMP_RULE_NOMARKUP": "{{ type }} {{ protocol }} traffic to ip {{ cidr }} of ICMP type {{ icmpTypeText }} [{{ icmpType }}] and ICMP code {{ icmpCodeText }} [{{ icmpCode }}]",
- "NO_TEXT_ICMP_RULE_NOMARKUP": "{{ type }} {{ protocol }} traffic to ip {{ cidr }} of ICMP type {{ icmpType }} and ICMP code {{ icmpCode }}",
- "NO_CODE_ICMP_RULE_NOMARKUP": "{{ type }} {{ protocol }} traffic to ip {{ cidr }} of ICMP type {{ icmpTypeText }} [{{ icmpType }}] and ICMP code {{ icmpCode }}",
+ "EGRESS_RULE": "{{ type }} {{ protocol }} traffic to {{ ipVersion }} {{ cidr }} to port {{ startPort }}",
+ "EGRESS_RULE_PORT_RANGE": "{{ type }} {{ protocol }} traffic to {{ ipVersion }} {{ cidr }} to port range {{ startPort }}-{{ endPort }}",
+ "EGRESS_ICMP_RULE": "{{ type }} {{ protocol }} traffic to {{ ipVersion }} {{ cidr }} of ICMP type {{ icmpTypeText }} [{{ icmpType }}] and ICMP code {{ icmpCodeText }} [{{ icmpCode }}]",
+ "NO_TEXT_EGRESS_ICMP_RULE": "{{ type }} {{ protocol }} traffic to {{ ipVersion }} {{ cidr }} of ICMP type {{ icmpType }} and ICMP code {{ icmpCode }}",
+ "NO_CODE_EGRESS_ICMP_RULE": "{{ type }} {{ protocol }} traffic to {{ ipVersion }} {{ cidr }} of ICMP type {{ icmpTypeText }} [{{ icmpType }}] and ICMP code {{ icmpCode }}",
+ "EGRESS_RULE_NOMARKUP": "{{ type }} {{ protocol }} traffic to {{ ipVersion }} {{ cidr }} to port {{ startPort }}",
+ "EGRESS_RULE_PORT_RANGE_NOMARKUP": "{{ type }} {{ protocol }} traffic to {{ ipVersion }} {{ cidr }} to port range {{ startPort }}-{{ endPort }}",
+ "EGRESS_ICMP_RULE_NOMARKUP": "{{ type }} {{ protocol }} traffic to {{ ipVersion }} {{ cidr }} of ICMP type {{ icmpTypeText }} [{{ icmpType }}] and ICMP code {{ icmpCodeText }} [{{ icmpCode }}]",
+ "NO_TEXT_EGRESS_ICMP_RULE_NOMARKUP": "{{ type }} {{ protocol }} traffic to {{ ipVersion }} {{ cidr }} of ICMP type {{ icmpType }} and ICMP code {{ icmpCode }}",
+ "NO_CODE_EGRESS_ICMP_RULE_NOMARKUP": "{{ type }} {{ protocol }} traffic to {{ ipVersion }} {{ cidr }} of ICMP type {{ icmpTypeText }} [{{ icmpType }}] and ICMP code {{ icmpCode }}",
+ "INGRESS_RULE": "{{ type }} {{ protocol }} traffic from {{ ipVersion }} {{ cidr }} to VM port {{ startPort }}",
+ "INGRESS_RULE_PORT_RANGE": "{{ type }} {{ protocol }} traffic from {{ ipVersion }} {{ cidr }} to VM port range {{ startPort }}-{{ endPort }}",
+ "INGRESS_ICMP_RULE": "{{ type }} {{ protocol }} traffic from {{ ipVersion }} {{ cidr }} of ICMP type {{ icmpTypeText }} [{{ icmpType }}] and ICMP code {{ icmpCodeText }} [{{ icmpCode }}]",
+ "NO_TEXT_INGRESS_ICMP_RULE": "{{ type }} {{ protocol }} traffic from {{ ipVersion }} {{ cidr }} of ICMP type {{ icmpType }} and ICMP code {{ icmpCode }}",
+ "NO_CODE_INGRESS_ICMP_RULE": "{{ type }} {{ protocol }} traffic from {{ ipVersion }} {{ cidr }} of ICMP type {{ icmpTypeText }} [{{ icmpType }}] and ICMP code {{ icmpCode }}",
+ "INGRESS_RULE_NOMARKUP": "{{ type }} {{ protocol }} traffic from {{ ipVersion }} {{ cidr }} to port {{ startPort }}",
+ "INGRESS_RULE_PORT_RANGE_NOMARKUP": "{{ type }} {{ protocol }} traffic from {{ ipVersion }} {{ cidr }} to VM port range {{ startPort }}-{{ endPort }}",
+ "INGRESS_ICMP_RULE_NOMARKUP": "{{ type }} {{ protocol }} traffic from {{ ipVersion }} {{ cidr }} of ICMP type {{ icmpTypeText }} [{{ icmpType }}] and ICMP code {{ icmpCodeText }} [{{ icmpCode }}]",
+ "NO_TEXT_INGRESS_ICMP_RULE_NOMARKUP": "{{ type }} {{ protocol }} traffic from {{ ipVersion }} {{ cidr }} of ICMP type {{ icmpType }} and ICMP code {{ icmpCode }}",
+ "NO_CODE_INGRESS_ICMP_RULE_NOMARKUP": "{{ type }} {{ protocol }} traffic from {{ ipVersion }} {{ cidr }} of ICMP type {{ icmpTypeText }} [{{ icmpType }}] and ICMP code {{ icmpCode }}",
"NO_FIREWALL_RULES": "No firewall rules"
},
"ICMP_TYPES": {
@@ -1037,6 +1049,213 @@
}
}
},
+ "ICMP_V6_TYPES": {
+ "1": {
+ "description": "Destination Unreachable Message",
+ "codes": {
+ "0": "No route to destination",
+ "1": "Communication with the destination is administratively prohibited, such as a firewall filter",
+ "2": "Not assigned",
+ "3": "Address unreachable",
+ "4": "Port unreachable",
+ "5": "Source address failed ingress/egress policy",
+ "6": "Reject route to destination"
+ }
+ },
+ "2": {
+ "description": "Packet Too Big Message",
+ "codes": {
+ "0": ""
+ }
+ },
+ "3": {
+ "description": "Time Exceeded Message",
+ "codes": {
+ "0": "Hop limit exceeded in transit",
+ "1": "Fragment reassembly time exceeded"
+ }
+ },
+ "4": {
+ "description": "Parameter Problem Message",
+ "codes": {
+ "0": "Erroneous header field encountered",
+ "1": "Unrecognized next header type encountered",
+ "2": "Unrecognized IPv6 option encountered"
+ }
+ },
+ "100": {
+ "description": "Private experimentation",
+ "codes": {
+ "0": ""
+ }
+ },
+ "101": {
+ "description": "Private experimentation",
+ "codes": {
+ "0": ""
+ }
+ },
+ "127": {
+ "description": "Reserved for expansion of ICMPv6 error messages",
+ "codes": {
+ "0": ""
+ }
+ },
+ "128": {
+ "description": "Echo Request",
+ "codes": {
+ "0": ""
+ }
+ },
+ "129": {
+ "description": "Echo Reply",
+ "codes": {
+ "0": ""
+ }
+ },
+ "130": {
+ "description": "Multicast Listener Query",
+ "codes": {
+ "0": ""
+ }
+ },
+ "131": {
+ "description": "Multicast Listener Report",
+ "codes": {
+ "0": ""
+ }
+ },
+ "132": {
+ "description": "Multicast Listener Done",
+ "codes": {
+ "0": ""
+ }
+ },
+ "133": {
+ "description": "Router Solicitation",
+ "codes": {
+ "0": ""
+ }
+ },
+ "134": {
+ "description": "Router Advertisement",
+ "codes": {
+ "0": ""
+ }
+ },
+ "135": {
+ "description": "Neighbor Solicitation",
+ "codes": {
+ "0": ""
+ }
+ },
+ "136": {
+ "description": "Neighbor Advertisement",
+ "codes": {
+ "0": ""
+ }
+ },
+ "137": {
+ "description": "Redirect Message",
+ "codes": {
+ "0": ""
+ }
+ },
+ "138": {
+ "description": "Router Renumbering",
+ "codes": {
+ "0": "Router Renumbering Command",
+ "1": "Router Renumbering Result",
+ "255": "Sequence Number Reset"
+ }
+ },
+ "139": {
+ "description": "ICMP Node Information Query",
+ "codes": {
+ "0": "The Data field contains an IPv6 address which is the Subject of this Query.",
+ "1": "The Data field contains a name which is the Subject of this Query, or is empty, as in the case of a NOOP.",
+ "2": "The Data field contains an IPv4 address which is the Subject of this Query."
+ }
+ },
+ "140": {
+ "description": "ICMP Node Information Response",
+ "codes": {
+ "0": "A successful reply. The Reply Data field may or may not be empty.",
+ "1": "The Responder refuses to supply the answer. The Reply Data field will be empty.",
+ "2": "The Qtype of the Query is unknown to the Responder. The Reply Data field will be empty."
+ }
+ },
+ "141": {
+ "description": "Inverse Neighbor Discovery",
+ "codes": {
+ "0": ""
+ }
+ },
+ "142": {
+ "description": "Inverse Neighbor Discovery",
+ "codes": {
+ "0": ""
+ }
+ },
+ "144": {
+ "description": "Home Agent Address Discovery",
+ "codes": {
+ "0": ""
+ }
+ },
+ "145": {
+ "description": "Home Agent Address Discovery",
+ "codes": {
+ "0": ""
+ }
+ },
+ "146": {
+ "description": "Mobile Prefix Solicitation",
+ "codes": {
+ "0": ""
+ }
+ },
+ "147": {
+ "description": "Mobile Prefix Advertisement",
+ "codes": {
+ "0": ""
+ }
+ },
+ "160": {
+ "description": "Extended Echo Request",
+ "codes": {
+ "0": "No error"
+ }
+ },
+ "161": {
+ "description": "Extended Echo Reply",
+ "codes": {
+ "0": "No error",
+ "1": "Malformed Query",
+ "2": "No Such Interface",
+ "3": "No Such Table Entry",
+ "4": "Multiple Interfaces Satisfy Query"
+ }
+ },
+ "200": {
+ "description": "Private experimentation",
+ "codes": {
+ "0": ""
+ }
+ },
+ "201": {
+ "description": "Private experimentation",
+ "codes": {
+ "0": ""
+ }
+ },
+ "255": {
+ "description": "Reserved for expansion of ICMPv6 informational messages",
+ "codes": {
+ "0": ""
+ }
+ }
+ },
"TEMPLATE_CREATION": {
"CREATE_NEW_TEMPLATE": "Create new template",
"CREATE_NEW_SHARED_GROUP": "Create new shared group",
diff --git a/src/i18n/ru.json b/src/i18n/ru.json
index db382cb0cc..08942f0d38 100644
--- a/src/i18n/ru.json
+++ b/src/i18n/ru.json
@@ -808,21 +808,33 @@
"ENTER_VALID_PORT": "Некорректный порт",
"ENTER_VALID_TYPE": "Некорректный тип",
"ENTER_VALID_CODE": "Некорректный код",
+ "ENTER_CIDR": "CIDR v4/v6",
"ENTER_VALID_CIDR": "Некорректный CIDR",
"FAILED_TO_ADD_RULE": "Не удалось добавить правило",
"FAILED_TO_REMOVE_RULE": "Не удалось удалить правило",
+ "SELECT_IP_VERSION": "Выберите версию IP",
"SELECT_TYPE": "Выберите типы",
"SELECT_PROTOCOL": "Выберите протоколы",
- "DEFAULT_RULE": "{{ type }} {{ protocol }} трафик до адреса {{ cidr }}, порт: {{ startPort }}",
- "DEFAULT_RULE_PORT_RANGE": "{{ type }} {{ protocol }} трафик до адреса {{ cidr }}, интервал портов: {{ startPort }}-{{ endPort }}",
- "DEFAULT_ICMP_RULE": "{{ type }} {{ protocol }} трафик до адреса {{ cidr }}, ICMP тип: {{ icmpTypeText }} [{{ icmpType }}], ICMP код: {{ icmpCodeText }} [{{ icmpCode }}]",
- "NO_TEXT_ICMP_RULE": "{{ type }} {{ protocol }} трафик до адреса {{ cidr }}, ICMP тип: {{ icmpType }}, ICMP код: {{ icmpCode }}",
- "NO_CODE_ICMP_RULE": "{{ type }} {{ protocol }} трафик до адреса {{ cidr }}, ICMP тип: {{ icmpTypeText }} [{{ icmpType }}], ICMP код: {{ icmpCode }}",
- "DEFAULT_RULE_NOMARKUP": "{{ type }} {{ protocol }} трафик до адреса {{ cidr }}, порт: {{ startPort }}",
- "DEFAULT_RULE_PORT_RANGE_NOMARKUP": "{{ type }} {{ protocol }} трафик до адреса {{ cidr }}, интервал портов: {{ startPort }}-{{ endPort }}",
- "DEFAULT_ICMP_RULE_NOMARKUP": "{{ type }} {{ protocol }} трафик до адреса {{ cidr }}, ICMP тип: {{ icmpTypeText }} [{{ icmpType }}], ICMP код: {{ icmpCodeText }} [{{ icmpCode }}]",
- "NO_TEXT_ICMP_RULE_NOMARKUP": "{{ type }} {{ protocol }} трафик до адреса {{ cidr }}, ICMP тип: {{ icmpType }}, ICMP код: {{ icmpCode }}",
- "NO_CODE_ICMP_RULE_NOMARKUP": "{{ type }} {{ protocol }} трафик до адреса {{ cidr }}, ICMP тип: {{ icmpTypeText }} [{{ icmpType }}], ICMP код: {{ icmpCode }}",
+ "EGRESS_RULE": "{{ type }} {{ protocol }} трафик до {{ ipVersion }} адреса {{ cidr }}, порт: {{ startPort }}",
+ "EGRESS_RULE_PORT_RANGE": "{{ type }} {{ protocol }} трафик до {{ ipVersion }} адреса {{ cidr }}, интервал портов: {{ startPort }}-{{ endPort }}",
+ "EGRESS_ICMP_RULE": "{{ type }} {{ protocol }} трафик до {{ ipVersion }} адреса {{ cidr }}, ICMP тип: {{ icmpTypeText }} [{{ icmpType }}], ICMP код: {{ icmpCodeText }} [{{ icmpCode }}]",
+ "NO_TEXT_EGRESS_ICMP_RULE": "{{ type }} {{ protocol }} трафик до {{ ipVersion }} адреса {{ cidr }}, ICMP тип: {{ icmpType }}, ICMP код: {{ icmpCode }}",
+ "NO_CODE_EGRESS_ICMP_RULE": "{{ type }} {{ protocol }} трафик до {{ ipVersion }} адреса {{ cidr }}, ICMP тип: {{ icmpTypeText }} [{{ icmpType }}], ICMP код: {{ icmpCode }}",
+ "EGRESS_RULE_NOMARKUP": "{{ type }} {{ protocol }} трафик до {{ ipVersion }} адреса {{ cidr }}, порт: {{ startPort }}",
+ "EGRESS_RULE_PORT_RANGE_NOMARKUP": "{{ type }} {{ protocol }} трафик до {{ ipVersion }} адреса {{ cidr }}, интервал портов: {{ startPort }}-{{ endPort }}",
+ "EGRESS_ICMP_RULE_NOMARKUP": "{{ type }} {{ protocol }} трафик до {{ ipVersion }} адреса {{ cidr }}, ICMP тип: {{ icmpTypeText }} [{{ icmpType }}], ICMP код: {{ icmpCodeText }} [{{ icmpCode }}]",
+ "NO_TEXT_EGRESS_ICMP_RULE_NOMARKUP": "{{ type }} {{ protocol }} трафик до {{ ipVersion }} адреса {{ cidr }}, ICMP тип: {{ icmpType }}, ICMP код: {{ icmpCode }}",
+ "NO_CODE_EGRESS_ICMP_RULE_NOMARKUP": "{{ type }} {{ protocol }} трафик до {{ ipVersion }} адреса {{ cidr }}, ICMP тип: {{ icmpTypeText }} [{{ icmpType }}], ICMP код: {{ icmpCode }}",
+ "INGRESS_RULE": "{{ type }} {{ protocol }} трафик с {{ ipVersion }} адреса {{ cidr }}, порт: {{ startPort }}",
+ "INGRESS_RULE_PORT_RANGE": "{{ type }} {{ protocol }} трафик с {{ ipVersion }} адреса {{ cidr }}, интервал портов: {{ startPort }}-{{ endPort }}",
+ "INGRESS_ICMP_RULE": "{{ type }} {{ protocol }} трафик с {{ ipVersion }} адреса {{ cidr }}, ICMP тип: {{ icmpTypeText }} [{{ icmpType }}], ICMP код: {{ icmpCodeText }} [{{ icmpCode }}]",
+ "NO_TEXT_INGRESS_ICMP_RULE": "{{ type }} {{ protocol }} трафик с {{ ipVersion }} адреса {{ cidr }}, ICMP тип: {{ icmpType }}, ICMP код: {{ icmpCode }}",
+ "NO_CODE_INGRESS_ICMP_RULE": "{{ type }} {{ protocol }} трафик с {{ ipVersion }} адреса {{ cidr }}, ICMP тип: {{ icmpTypeText }} [{{ icmpType }}], ICMP код: {{ icmpCode }}",
+ "INGRESS_RULE_NOMARKUP": "{{ type }} {{ protocol }} трафик с {{ ipVersion }} адреса {{ cidr }}, порт: {{ startPort }}",
+ "INGRESS_RULE_PORT_RANGE_NOMARKUP": "{{ type }} {{ protocol }} трафик с {{ ipVersion }} адреса {{ cidr }}, интервал портов: {{ startPort }}-{{ endPort }}",
+ "INGRESS_ICMP_RULE_NOMARKUP": "{{ type }} {{ protocol }} трафик с {{ ipVersion }} адреса {{ cidr }}, ICMP тип: {{ icmpTypeText }} [{{ icmpType }}], ICMP код: {{ icmpCodeText }} [{{ icmpCode }}]",
+ "NO_TEXT_INGRESS_ICMP_RULE_NOMARKUP": "{{ type }} {{ protocol }} трафик с {{ ipVersion }} адреса {{ cidr }}, ICMP тип: {{ icmpType }}, ICMP код: {{ icmpCode }}",
+ "NO_CODE_INGRESS_ICMP_RULE_NOMARKUP": "{{ type }} {{ protocol }} трафик с {{ ipVersion }} адреса {{ cidr }}, ICMP тип: {{ icmpTypeText }} [{{ icmpType }}], ICMP код: {{ icmpCode }}",
"NO_FIREWALL_RULES": "Нет правил брандмауэра"
},
"ICMP_TYPES": {
@@ -1033,6 +1045,213 @@
}
}
},
+ "ICMP_V6_TYPES": {
+ "1": {
+ "description": "Сообщение о недоступности назначения",
+ "codes": {
+ "0": "Никакой маршрут назначению",
+ "1": "Связь с назначением административно не запрещен, такие как фильтр межсетевого экрана",
+ "2": "Не назначенный",
+ "3": "Недостижимый адрес",
+ "4": "Недостижимый порт",
+ "5": "Source address failed ingress/egress policy",
+ "6": "Reject route to destination"
+ }
+ },
+ "2": {
+ "description": "Сообщение о слишком большом пакете",
+ "codes": {
+ "0": ""
+ }
+ },
+ "3": {
+ "description": "Time Exceeded Message",
+ "codes": {
+ "0": "Предел перехода превысил в транзите",
+ "1": "Время повторной сборки фрагмента превысило"
+ }
+ },
+ "4": {
+ "description": "Сообщение о проблеме параметра",
+ "codes": {
+ "0": "Ошибочное поле заголовка встретилось",
+ "1": "Неопознанный следующий тип заголовка встретился",
+ "2": "Unrecognized IPv6"
+ }
+ },
+ "100": {
+ "description": "Private experimentation",
+ "codes": {
+ "0": ""
+ }
+ },
+ "101": {
+ "description": "Private experimentation",
+ "codes": {
+ "0": ""
+ }
+ },
+ "127": {
+ "description": "Reserved for expansion of ICMPv6 error messages",
+ "codes": {
+ "0": ""
+ }
+ },
+ "128": {
+ "description": "Сообщение запроса эха",
+ "codes": {
+ "0": ""
+ }
+ },
+ "129": {
+ "description": "Сообщение эхо-ответа",
+ "codes": {
+ "0": ""
+ }
+ },
+ "130": {
+ "description": "Multicast Listener Query",
+ "codes": {
+ "0": ""
+ }
+ },
+ "131": {
+ "description": "Multicast Listener Report",
+ "codes": {
+ "0": ""
+ }
+ },
+ "132": {
+ "description": "Multicast Listener Done",
+ "codes": {
+ "0": ""
+ }
+ },
+ "133": {
+ "description": "Сообщение запроса маршрутизатора",
+ "codes": {
+ "0": ""
+ }
+ },
+ "134": {
+ "description": "Сообщение объявления маршрутизатора",
+ "codes": {
+ "0": ""
+ }
+ },
+ "135": {
+ "description": "Сообщение Neighbor Solicitation",
+ "codes": {
+ "0": ""
+ }
+ },
+ "136": {
+ "description": "Сообщение об объявлении окружения",
+ "codes": {
+ "0": ""
+ }
+ },
+ "137": {
+ "description": "Сообщение перенаправления",
+ "codes": {
+ "0": ""
+ }
+ },
+ "138": {
+ "description": "Router Renumbering",
+ "codes": {
+ "0": "Router Renumbering Command",
+ "1": "Router Renumbering Result",
+ "255": "Sequence Number Reset"
+ }
+ },
+ "139": {
+ "description": "ICMP Node Information Query",
+ "codes": {
+ "0": "The Data field contains an IPv6 address which is the Subject of this Query.",
+ "1": "The Data field contains a name which is the Subject of this Query, or is empty, as in the case of a NOOP.",
+ "2": "The Data field contains an IPv4 address which is the Subject of this Query."
+ }
+ },
+ "140": {
+ "description": "ICMP Node Information Response",
+ "codes": {
+ "0": "A successful reply. The Reply Data field may or may not be empty.",
+ "1": "The Responder refuses to supply the answer. The Reply Data field will be empty.",
+ "2": "The Qtype of the Query is unknown to the Responder. The Reply Data field will be empty."
+ }
+ },
+ "141": {
+ "description": "Inverse Neighbor Discovery",
+ "codes": {
+ "0": ""
+ }
+ },
+ "142": {
+ "description": "Inverse Neighbor Discovery",
+ "codes": {
+ "0": ""
+ }
+ },
+ "144": {
+ "description": "Home Agent Address Discovery",
+ "codes": {
+ "0": ""
+ }
+ },
+ "145": {
+ "description": "Home Agent Address Discovery",
+ "codes": {
+ "0": ""
+ }
+ },
+ "146": {
+ "description": "Mobile Prefix Solicitation",
+ "codes": {
+ "0": ""
+ }
+ },
+ "147": {
+ "description": "Mobile Prefix Advertisement",
+ "codes": {
+ "0": ""
+ }
+ },
+ "160": {
+ "description": "Extended Echo Request",
+ "codes": {
+ "0": "No error"
+ }
+ },
+ "161": {
+ "description": "Extended Echo Reply",
+ "codes": {
+ "0": "No error",
+ "1": "Malformed Query",
+ "2": "No Such Interface",
+ "3": "No Such Table Entry",
+ "4": "Multiple Interfaces Satisfy Query"
+ }
+ },
+ "200": {
+ "description": "Private experimentation",
+ "codes": {
+ "0": ""
+ }
+ },
+ "201": {
+ "description": "Private experimentation",
+ "codes": {
+ "0": ""
+ }
+ },
+ "255": {
+ "description": "Reserved for expansion of ICMPv6 informational messages",
+ "codes": {
+ "0": ""
+ }
+ }
+ },
"TEMPLATE_CREATION": {
"CREATE_NEW_TEMPLATE": "Создать новый шаблон",
"CREATE_NEW_SHARED_GROUP": "Создать новую разделяемую группу",
diff --git a/src/testutils/mocks/model-services/services/mock-security-group.service.spec.ts b/src/testutils/mocks/model-services/services/mock-security-group.service.spec.ts
index 6ee751d892..08792e8b12 100644
--- a/src/testutils/mocks/model-services/services/mock-security-group.service.spec.ts
+++ b/src/testutils/mocks/model-services/services/mock-security-group.service.spec.ts
@@ -1,12 +1,11 @@
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
-import { SecurityGroup, SecurityGroupType } from '../../../../app/security-group/sg.model';
-
+import { SecurityGroup } from '../../../../app/security-group/sg.model';
const securityGroupTemplates: Array