Skip to content

Commit

Permalink
Merge pull request #489 from broadinstitute/sdarq-remove-seccon-endpoint
Browse files Browse the repository at this point in the history
[DSEC-743][sdarq][backend][frontend] Add remove endpoint and service for SecCon
  • Loading branch information
zbedo authored Nov 4, 2023
2 parents 0c9b712 + e453f30 commit cfe658f
Show file tree
Hide file tree
Showing 16 changed files with 231 additions and 7 deletions.
55 changes: 55 additions & 0 deletions sdarq/backend/src/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,61 @@ def edit_sec_controls():
return jsonify({'statusText': message}), 400


@app.route('/delete_service_sec_controls/', methods=['POST'])
@cross_origin(origins=sdarq_host)
def delete_service_sec_controls():
"""
Delete security controls for a service
Args: Provided json data from user
Returns: 200 status if data remove successfully
404 if service not found
400 is there is an error
"""
json_data = request.get_json()
service_name = json_data['service']
pattern = "^[a-zA-Z0-9][a-zA-Z0-9-_ ]{1,28}[a-zA-Z0-9]$"
user_email = request.headers.get('X-Goog-Authenticated-User-Email')

if request.headers.get('Content-Type') != 'application/json':
return jsonify({'statusText': 'Bad Request'}), 400

if re.match(pattern, service_name):
try:
validate(instance=json_data, schema=edit_security_controls_schema)
doc_ref = db.collection(security_controls_firestore_collection).document(
service_name.lower())
doc = doc_ref.get()
if bool(doc.to_dict()) is True:
db.collection(security_controls_firestore_collection).document(service_name.lower()).delete()
logging.info("Security control %s for the choosen service are removed by %s !",
service_name, user_email)
return ''
else:
message = """
This service does not exist!
"""
logging.info(
"User %s requested to remove service security controls, but this service does not exist!",
user_email)
return jsonify({'statusText': message}), 404
except Exception as error:
error_message = f"Exception /delete_service_sec_controls endpoint: {error}"
slacknotify.slacknotify_error_endpoint(error_message, appsec_sdarq_error_channel, user_email)
logging.warning(error_message)
message = """
There is something wrong with the input! Server did not respond correctly to your request!
"""
return jsonify({'statusText': message}), 400
else:
message = """
Invalid input! Please make sure you include numbers, -, _ and alphabetical characters.
"""
logging.info(
"User %s requested to remove Security Controls for a service, but INVALID input was provided",
user_email)
return jsonify({'statusText': message}), 400


@app.route('/get_sec_controls/', methods=['GET'])
@cross_origin(origins=sdarq_host)
def get_sec_controls():
Expand Down
2 changes: 1 addition & 1 deletion sdarq/backend/src/schemas/edit_security_controls_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
},
"github": {
"type": "string",
"pattern": "^(https:\/\/github\.com\/[a-zA-Z0-9-]+\/[a-zA-Z0-9-]+|(N\/A))$"
"pattern": "^(https://github.com/[a-zA-Z0-9-]+/[a-zA-Z0-9-]+|(N/A))$"
},
"threat_model": {
"type": "boolean",
Expand Down
2 changes: 1 addition & 1 deletion sdarq/backend/src/schemas/new_service_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
},
"Github URL": {
"type": "string",
"pattern": "^(https:\/\/github\.com\/[a-zA-Z0-9-]+\/[a-zA-Z0-9-]+|(N\/A))$"
"pattern": "^(https://github.com/[a-zA-Z0-9-]+/[a-zA-Z0-9-]+|(N/A))$"
},
"Architecture Diagram": {
"type": "string",
Expand Down
2 changes: 1 addition & 1 deletion sdarq/backend/src/schemas/security_controls_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
},
"github": {
"type": "string",
"pattern": "^(https:\/\/github\.com\/[a-zA-Z0-9-]+\/[a-zA-Z0-9-]+|(N\/A))$"
"pattern": "^(https://github.com/[a-zA-Z0-9-]+/[a-zA-Z0-9-]+|(N/A))$"
},
"dev_url": {
"type": "string",
Expand Down
2 changes: 1 addition & 1 deletion sdarq/backend/src/schemas/threat_model_request_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"properties": {
"Type": {
"type": "string",
"pattern": "^[a-zA-Z0-9][a-zA-Z0-9\\s]{1,30}[a-zA-Z0-9\s]$"
"pattern": "^[a-zA-Z0-9][a-zA-Z0-9\s]{1,30}[a-zA-Z0-9\s]$"
},
"Name": {
"type": "string",
Expand Down
2 changes: 2 additions & 0 deletions sdarq/frontend/src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { AppFormComponent } from './app-form/app-form.component';
import { AppsMainpageComponent } from './apps-mainpage/apps-mainpage.component';
import { ServiceSecurityControlsComponent } from './service-security-controls/service-security-controls.component';
import { SearchServiceSecurityControlsComponent } from './search-service-security-controls/search-service-security-controls.component';
import { DeleteServiceSecurityControlsComponent } from './delete-service-security-controls/delete-service-security-controls.component';


const routes: Routes = [
Expand All @@ -46,6 +47,7 @@ const routes: Routes = [
{ path: 'security-pentest/request', component: SecurityPentestComponent },
{ path: 'service-security-controls/results', component: ServiceSecurityControlsComponent },
{ path: 'search-service-security-controls', component: SearchServiceSecurityControlsComponent },
{ path: 'security-control/delete-service', component: DeleteServiceSecurityControlsComponent },
{ path: '404', component: NotfoundComponent },
{ path: '**', redirectTo: '/404' }
];
Expand Down
10 changes: 7 additions & 3 deletions sdarq/frontend/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ import { AppFormComponent } from './app-form/app-form.component';
import { AppsMainpageComponent } from './apps-mainpage/apps-mainpage.component';
import { ServiceSecurityControlsComponent } from './service-security-controls/service-security-controls.component';
import { SearchServiceSecurityControlsComponent } from './search-service-security-controls/search-service-security-controls.component';
import { DeleteServiceSecurityControlsComponent } from './delete-service-security-controls/delete-service-security-controls.component';
import { DeleteServiceSecurityControlsService } from './services/delete-service-security-controls/delete-service-security-controls.service';


@NgModule({
Expand Down Expand Up @@ -79,10 +81,11 @@ import { SearchServiceSecurityControlsComponent } from './search-service-securit
AppFormComponent,
AppsMainpageComponent,
ServiceSecurityControlsComponent,
SearchServiceSecurityControlsComponent
SearchServiceSecurityControlsComponent,
DeleteServiceSecurityControlsComponent
],
imports: [
BrowserModule,
BrowserModule,
FormsModule,
HttpClientModule,
AppRoutingModule,
Expand All @@ -103,7 +106,8 @@ import { SearchServiceSecurityControlsComponent } from './search-service-securit
GetServiceSecurityControlsService,
RequestSecurityPentestService,
JiraTicketRiskAssessmentService,
SendAppFormDataService
SendAppFormDataService,
DeleteServiceSecurityControlsService
],
bootstrap: [
AppComponent
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<div class="jumbotron min-vh-100">
<div class="container">
<div class="alert alert-danger animated fadeInRight" role="alert" *ngIf="showModalErr">
<h4 class="alert-heading">Oops!</h4>
<p> {{error_message}} </p>
<p class="mb-0">Please contact AppSec team for more information!</p>
</div>
<br>
<br>
<app-survey *ngIf="showForm" [json]="json" (submitSurvey)="sendData($event)"></app-survey>
<br>
<br>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { DeleteServiceSecurityControlsComponent } from './delete-service-security-controls.component';

describe('DeleteServiceSecurityControlsComponent', () => {
let component: DeleteServiceSecurityControlsComponent;
let fixture: ComponentFixture<DeleteServiceSecurityControlsComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ DeleteServiceSecurityControlsComponent ]
})
.compileComponents();

fixture = TestBed.createComponent(DeleteServiceSecurityControlsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { ChangeDetectorRef, Component, NgZone, OnInit } from '@angular/core';
import { DeleteServiceSecurityControlsService } from '../services/delete-service-security-controls/delete-service-security-controls.service';
import formJson from './form.json';

@Component({
selector: 'app-delete-service-security-controls',
templateUrl: './delete-service-security-controls.component.html',
styleUrls: ['./delete-service-security-controls.component.css']
})
export class DeleteServiceSecurityControlsComponent implements OnInit {

showModalErr: boolean;
showForm: boolean;
json = formJson;
error_message: string;

constructor(private DeleteServiceSecurityControls: DeleteServiceSecurityControlsService,
private ref: ChangeDetectorRef,
private ngZone: NgZone) {
// This is intentional
}

ngOnInit(): void {
this.showForm = true;
}

sendData(result) {
this.DeleteServiceSecurityControls.removeSecurityControls(result).subscribe(() => {
this.ref.detectChanges();
},
(data) => {
this.ngZone.run(() => {
this.showModalErr = true;
this.showForm = false;
this.error_message = data;
});
});

}
}
20 changes: 20 additions & 0 deletions sdarq/frontend/src/app/delete-service-security-controls/form.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"pages": [{
"name": "Delete security controls for service",
"elements": [{
"type": "text",
"name": "service",
"title": "Enter service name",
"isRequired": true,
"requiredErrorText": "Service name is required.",
"validators": [{
"type": "regex",
"text": "Please enter a valid service name",
"regex": "^[a-zA-Z0-9][a-zA-Z0-9-_ ]{1,40}[a-zA-Z0-9]$"
}]
}],
"title": "Delete security controls for service"
}],
"showCompletedPage": false,
"showQuestionNumbers": "off"
}
1 change: 1 addition & 0 deletions sdarq/frontend/src/app/navbar/navbar.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
<li><a class="dropdown-item" href="/security-control/view">List security controls</a></li>
<li><a class="dropdown-item" href="/security-control/create">Add new security controls</a></li>
<li><a class="dropdown-item" href="/security-control/edit">Edit security controls</a></li>
<li><a class="dropdown-item" href="security-control/delete-service">Remove service security controls</a></li>
</ul>
</li>
<li class="nav-item dropdown">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';

import { DeleteServiceSecurityControlsService } from './delete-service-security-controls.service';

describe('DeleteServiceSecurityControlsService', () => {
let service: DeleteServiceSecurityControlsService;

beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(DeleteServiceSecurityControlsService);
});

it('should be created', () => {
expect(service).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Injectable } from '@angular/core';
import { Observable, throwError } from 'rxjs';
import { HttpHeaders, HttpClient } from '@angular/common/http';
import { catchError } from 'rxjs/operators';

@Injectable({
providedIn: 'root'
})
export class DeleteServiceSecurityControlsService {

private Url = location.origin + '/delete_service_sec_controls/';

constructor(private http: HttpClient) { }

removeSecurityControls(data): Observable<any> {
const options = {
headers: new HttpHeaders({ 'Content-Type': 'application/json'}),
};
return this.http.post(this.Url, data, options).pipe(
catchError(this.handleError)
)
}

handleError(error) {

let errorMessage = '';

if (error.error instanceof ErrorEvent) {
// client-side error
errorMessage = `${error.error.message}`;
} else {
// server-side error
if (error.error.statusText) {
errorMessage = `${error.error.statusText}`;
} else {
errorMessage = `${error.message}`;
}
}
return throwError(errorMessage);
}
}

7 changes: 7 additions & 0 deletions sdarq/ingress.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@ spec:
name: ${SERVICE}
port:
name: ${BACKEND_PORT}
- path: /delete_service_sec_controls/
pathType: ImplementationSpecific
backend:
service:
name: ${SERVICE}
port:
name: ${BACKEND_PORT}
---
apiVersion: networking.gke.io/v1beta1
kind: FrontendConfig
Expand Down

0 comments on commit cfe658f

Please sign in to comment.