/* * @license * Copyright 2018 Brigham Young University * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { expect } from 'chai'; import { BindContext, PreDeployContext, ServiceContext, ServiceType, UnBindContext } from 'handel-extension-api'; import 'mocha'; import * as sinon from 'sinon'; import * as ec2Calls from '../../../src/aws/ec2-calls'; import { SharedDbConfig } from '../../../src/services/shared-db/config-types'; import * as securityGroups from '../../../src/services/shared-db/security-groups'; import accountConfig from '../../fake-account-config'; describe('security groups module', () => { let sandbox: sinon.SinonSandbox; const serviceParams: SharedDbConfig = { type: 'shared-db', cluster_id: 'FakeClusterId', schema_migrations_dir: '.' }; const appName = 'FakeApp'; const envName = 'FakeService'; const serviceContext = new ServiceContext(appName, envName, 'FakeService', new ServiceType('byu', 'mysql'), serviceParams, accountConfig); beforeEach(async () => { sandbox = sinon.sandbox.create(); }); afterEach(() => { sandbox.restore(); }); describe('bindToOneOfSharedSGs', () => { const preDeployContext = new PreDeployContext(serviceContext); preDeployContext.securityGroups.push({ GroupId: 'OwnSg', IpPermissions: [] }); const dependentOfServiceContext = new ServiceContext('FakeApp', 'FakeEnv', 'FakeService', new ServiceType('byu', 'kubernetes'), { type: 'kubernetes' }, accountConfig); const dependentOfPreDeployContext = new PreDeployContext(dependentOfServiceContext); dependentOfPreDeployContext.securityGroups.push({ GroupId: 'SourceSg', IpPermissions: [] }); it('should bind to one of the shared RDS security groups if it doesnt have an ingress rule yet', async () => { const ingressExistsStub = sandbox.stub(ec2Calls, 'ingressRuleExists').returns(false); const addIngressStub = sandbox.stub(ec2Calls, 'addIngressRuleToSecurityGroup').resolves({}); const bindContext = await securityGroups.bindToOneOfSharedSGs(serviceContext, preDeployContext, dependentOfServiceContext, dependentOfPreDeployContext, 3306); expect(ingressExistsStub.callCount).to.equal(1); expect(addIngressStub.callCount).to.equal(1); expect(bindContext).to.be.instanceof(BindContext); }); it('should leave the existing ingress rule if one already exists for the bind', async () => { const ingressExistsStub = sandbox.stub(ec2Calls, 'ingressRuleExists').returns(true); const addIngressStub = sandbox.stub(ec2Calls, 'addIngressRuleToSecurityGroup').resolves({}); const bindContext = await securityGroups.bindToOneOfSharedSGs(serviceContext, preDeployContext, dependentOfServiceContext, dependentOfPreDeployContext, 3306); expect(ingressExistsStub.callCount).to.equal(1); expect(addIngressStub.callCount).to.equal(0); expect(bindContext).to.be.instanceof(BindContext); }); }); describe('getSharedRdsSgs', () => { it('should return the list of security groups for the RDS instance', async () => { const getSgsStub = sandbox.stub(ec2Calls, 'getSecurityGroupsByNameTag').resolves([{ GroupId: 'fakeId' }]); const sgs = await securityGroups.getSharedRdsSgs(serviceContext, 'FakeTag'); expect(getSgsStub.callCount).to.equal(1); expect(sgs.length).to.equal(1); }); }); describe('unBindFromSharedSgs', () => { it('should unbind from the security groups (if any) and return an unbind context', async () => { const vpcId = 'FakeVpc'; const sourceSg: AWS.EC2.SecurityGroup = { GroupId: 'OwnSg', IpPermissions: [] }; const preDeployContext = new PreDeployContext(serviceContext); preDeployContext.securityGroups = [ { GroupId: 'OwnSg1', IpPermissions: [] }, { GroupId: 'OwnSg2', IpPermissions: [ { IpProtocol: 'tcp', FromPort: 3306, ToPort: 3306, UserIdGroupPairs: [ { GroupId: sourceSg.GroupId, VpcId: vpcId } ] } ] } ]; const dependentOfServiceContext = new ServiceContext('FakeApp', 'FakeEnv', 'FakeService', new ServiceType('byu', 'kubernetes'), { type: 'kubernetes' }, accountConfig); const dependentOfPreDeployContext = new PreDeployContext(dependentOfServiceContext); dependentOfPreDeployContext.securityGroups.push(sourceSg); const ingressExistsSpy = sandbox.spy(ec2Calls, 'ingressRuleExists'); const removeIngressStub = sandbox.stub(ec2Calls, 'removeIngressFromSg').resolves(true); const unBindContext = await securityGroups.unBindFromSharedSgs(serviceContext, preDeployContext, dependentOfServiceContext, dependentOfPreDeployContext, 3306); expect(ingressExistsSpy.callCount).to.equal(2); expect(ingressExistsSpy.getCall(0).returned(false)).to.equal(true); expect(ingressExistsSpy.getCall(1).returned(true)).to.equal(true); expect(removeIngressStub.callCount).to.equal(1); expect(unBindContext).to.be.instanceof(UnBindContext); }); }); });