Skip to content
This repository has been archived by the owner on Mar 25, 2023. It is now read-only.

Commit

Permalink
feat(security-group): Support IPv6 (closes #671) (#957)
Browse files Browse the repository at this point in the history
  • Loading branch information
Darya Baklanova authored Feb 12, 2018
1 parent 51e9f82 commit b2a8da0
Show file tree
Hide file tree
Showing 13 changed files with 863 additions and 189 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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"
Expand Down
20 changes: 15 additions & 5 deletions src/app/security-group/sg-rules/sg-rule.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,39 @@
<ng-template [ngIf]="item.protocol === NetworkProtocols.ICMP">
<ng-template [ngIf]="!ruleParams['icmpTypeText'] && !ruleParams['icmpCodeText']">
<span
[innerHTML]="'SECURITY_GROUP_PAGE.RULES.NO_TEXT_ICMP_RULE' | translate: (ruleParams)"
[innerHTML]="(item.type === NetworkRuleTypes.Ingress
? 'SECURITY_GROUP_PAGE.RULES.NO_TEXT_INGRESS_ICMP_RULE'
: 'SECURITY_GROUP_PAGE.RULES.NO_TEXT_EGRESS_ICMP_RULE') | translate: (ruleParams)"
></span>
</ng-template>
<ng-template [ngIf]="!!ruleParams['icmpTypeText'] && !ruleParams['icmpCodeText']">
<span
[innerHTML]="'SECURITY_GROUP_PAGE.RULES.NO_CODE_ICMP_RULE' | translate: (ruleParams)"
[innerHTML]="(item.type === NetworkRuleTypes.Ingress
? 'SECURITY_GROUP_PAGE.RULES.NO_CODE_INGRESS_ICMP_RULE'
: 'SECURITY_GROUP_PAGE.RULES.NO_CODE_EGRESS_ICMP_RULE') | translate: (ruleParams)"
></span>
</ng-template>
<ng-template [ngIf]="!!ruleParams['icmpTypeText'] && !!ruleParams['icmpCodeText']">
<span
[innerHTML]="'SECURITY_GROUP_PAGE.RULES.DEFAULT_ICMP_RULE' | translate: (ruleParams)"
[innerHTML]="(item.type === NetworkRuleTypes.Ingress
? 'SECURITY_GROUP_PAGE.RULES.INGRESS_ICMP_RULE'
: 'SECURITY_GROUP_PAGE.RULES.EGRESS_ICMP_RULE') | translate: (ruleParams)"
></span>
</ng-template>
</ng-template>
<ng-template [ngIf]="item.protocol !== NetworkProtocols.ICMP">
<ng-template [ngIf]="item.startPort === item.endPort">
<span
[innerHTML]=" 'SECURITY_GROUP_PAGE.RULES.DEFAULT_RULE' | translate: (ruleParams)"
[innerHTML]="(item.type === NetworkRuleTypes.Ingress
? 'SECURITY_GROUP_PAGE.RULES.INGRESS_RULE'
: 'SECURITY_GROUP_PAGE.RULES.EGRESS_RULE') | translate: (ruleParams)"
></span>
</ng-template>
<ng-template [ngIf]="item.startPort !== item.endPort">
<span
[innerHTML]="'SECURITY_GROUP_PAGE.RULES.DEFAULT_RULE_PORT_RANGE' | translate: (ruleParams)"
[innerHTML]="(item.type === NetworkRuleTypes.Ingress
? 'SECURITY_GROUP_PAGE.RULES.INGRESS_RULE_PORT_RANGE'
: 'SECURITY_GROUP_PAGE.RULES.EGRESS_RULE_PORT_RANGE') | translate: (ruleParams)"
></span>
</ng-template>
</ng-template>
Expand Down
19 changes: 16 additions & 3 deletions src/app/security-group/sg-rules/sg-rule.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -25,6 +28,7 @@ export class SgRuleComponent {

public deleting = false;
public NetworkProtocols = NetworkProtocol;
public NetworkRuleTypes = NetworkRuleType;

public get typeTranslationToken(): string {
const typeTranslations = {
Expand All @@ -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;
Expand Down
31 changes: 24 additions & 7 deletions src/app/security-group/sg-rules/sg-rules.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -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"
>
<mat-error *ngIf="cidrField.hasError('pattern')">
<mat-error *ngIf="!isCidrValid(cidr)">
{{ 'SECURITY_GROUP_PAGE.RULES.ENTER_VALID_CIDR' | translate }}
</mat-error>
</mat-form-field>
Expand All @@ -62,7 +63,7 @@
<input
matInput
maxValue="255"
minValue="-1"
[minValue]="cidrIpVersion === IPVersion.ipv6 ? 0 : -1"
#icmpTypeField="ngModel"
name="icmpType"
[placeholder]="'SECURITY_GROUP_PAGE.RULES.ICMP_TYPE' | translate"
Expand All @@ -89,7 +90,7 @@
type="number"
[(ngModel)]="startPort"
[minValue]="0"
[maxValue]="65536"
[maxValue]="65535"
[placeholder]="'SECURITY_GROUP_PAGE.RULES.START_PORT' | translate"
integerValue
required
Expand All @@ -108,7 +109,7 @@
matInput
name="icmpCode"
maxValue="255"
minValue="-1"
[minValue]="cidrIpVersion === IPVersion.ipv6 ? 0 : -1"
#icmpCodeField="ngModel"
[placeholder]="'SECURITY_GROUP_PAGE.RULES.ICMP_CODE' | translate"
[matAutocomplete]="icmpCodesAuto"
Expand Down Expand Up @@ -137,7 +138,7 @@
type="number"
[(ngModel)]="endPort"
[minValue]="0"
[maxValue]="65536"
[maxValue]="65535"
[placeholder]="'SECURITY_GROUP_PAGE.RULES.END_PORT' | translate"
integerValue
required
Expand Down Expand Up @@ -169,6 +170,22 @@
</table>

<div *ngIf="!editMode">
<mat-form-field class="form-select-control">
<mat-select
multiple="true"
[placeholder]="'SECURITY_GROUP_PAGE.RULES.SELECT_IP_VERSION' | translate"
[(ngModel)]="selectedIPVersion"
(selectionChange)="filter()"
name="selectedIPVersion"
>
<mat-option
*ngFor="let t of IPversions"
[value]="t"
>
{{ t }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field class="form-select-control">
<mat-select
multiple="true"
Expand Down
122 changes: 115 additions & 7 deletions src/app/security-group/sg-rules/sg-rules.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,20 @@ import { Observable } from 'rxjs/Observable';
import { MockNotificationService } from '../../../testutils/mocks/mock-notification.service';
import { MockTranslatePipe } from '../../../testutils/mocks/mock-translate.pipe.spec';
import { MockTranslateService } from '../../../testutils/mocks/mock-translate.service.spec';
import { ICMPv6Types } from '../../shared/icmp/icmp-types';
import { NotificationService } from '../../shared/services/notification.service';
import { SecurityGroupService } from '../services/security-group.service';
import { NetworkRuleType, SecurityGroup } from '../sg.model';
import { IPVersion, NetworkRuleType, SecurityGroup } from '../sg.model';
import { SgRulesComponent } from './sg-rules.component';
import { NetworkRule } from '../network-rule.model';
import { NetworkProtocol, NetworkRule } from '../network-rule.model';
import { NetworkRuleService } from '../services/network-rule.service';
import { DialogService } from '../../dialog/dialog-service/dialog.service';
import { Router } from '@angular/router';
import { LoadingDirective } from '../../shared/directives/loading.directive';

const securityGroupTemplates: Array<Object> = require(
'../../../testutils/mocks/model-services/fixtures/securityGroupTemplates.json');

@Injectable()
class MockRouter {
public navigate(route: any): Promise<any> {
Expand All @@ -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<SecurityGroup> {
Expand Down Expand Up @@ -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();
}));
});
Loading

0 comments on commit b2a8da0

Please sign in to comment.