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 = require('../fixtures/securityGroupTemplates.json'); @Injectable() -export class MockServiceOfferingService { +export class MockSecurityGroupService { public getList(): Observable> { return Observable.of(securityGroupTemplates.map(json => new SecurityGroup(json))); } diff --git a/yarn.lock b/yarn.lock index b730f23571..b63a5410e0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2914,6 +2914,18 @@ invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" +ip-address@^5.8.9: + version "5.8.9" + resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-5.8.9.tgz#6379277c23fc5adb20511e4d23ec2c1bde105dfd" + dependencies: + jsbn "1.1.0" + lodash.find "^4.6.0" + lodash.max "^4.0.1" + lodash.merge "^4.6.0" + lodash.padstart "^4.6.1" + lodash.repeat "^4.1.0" + sprintf-js "1.1.0" + ip@^1.1.0, ip@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" @@ -3270,6 +3282,10 @@ js-yaml@~3.7.0: argparse "^1.0.7" esprima "^2.6.0" +jsbn@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-1.1.0.tgz#b01307cb29b618a1ed26ec79e911f803c4da0040" + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" @@ -3544,14 +3560,34 @@ lodash.clonedeep@^4.3.2, lodash.clonedeep@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" +lodash.find@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.find/-/lodash.find-4.6.0.tgz#cb0704d47ab71789ffa0de8b97dd926fb88b13b1" + +lodash.max@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.max/-/lodash.max-4.0.1.tgz#8735566c618b35a9f760520b487ae79658af136a" + lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" +lodash.merge@^4.6.0: + version "4.6.1" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.1.tgz#adc25d9cb99b9391c59624f379fbba60d7111d54" + lodash.mergewith@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.0.tgz#150cf0a16791f5903b8891eab154609274bdea55" +lodash.padstart@^4.6.1: + version "4.6.1" + resolved "https://registry.yarnpkg.com/lodash.padstart/-/lodash.padstart-4.6.1.tgz#d2e3eebff0d9d39ad50f5cbd1b52a7bce6bb611b" + +lodash.repeat@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/lodash.repeat/-/lodash.repeat-4.1.0.tgz#fc7de8131d8c8ac07e4b49f74ffe829d1f2bec44" + lodash.tail@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.tail/-/lodash.tail-4.1.1.tgz#d2333a36d9e7717c8ad2f7cacafec7c32b444664" @@ -5459,7 +5495,11 @@ split@^1.0.0: dependencies: through "2" -sprintf-js@^1.0.3: +sprintf-js@1.1.0, sprintf-js@^1.0.3: + version "1.1.0" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.0.tgz#cffcaf702daf65ea39bb4e0fa2b299cec1a1be46" + +sprintf-js@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.1.tgz#36be78320afe5801f6cea3ee78b6e5aab940ea0c"