Skip to content

Commit

Permalink
feat(305172): add MobSF security scan on android and iOS builds for s…
Browse files Browse the repository at this point in the history
…taging and prod
  • Loading branch information
Arieldelossantos committed Jul 10, 2024
1 parent cb75a04 commit 4379aa3
Show file tree
Hide file tree
Showing 8 changed files with 409 additions and 5 deletions.
20 changes: 20 additions & 0 deletions build/azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,16 @@ stages:
applicationEnvironment: Staging
deploymentEnvironment: TestFlight

# MOBSF SECURITY SCAN STAGING
- stage: Security_Scan_Build_Staging
dependsOn: Build_Staging
jobs:
- template: stage-security-scan.yml
parameters:
applicationEnvironment: Staging
enableIosSecurityScan: true
enableAndroidSecurityScan: true

- stage: Build_Production
dependsOn: Build_Staging
condition: and(succeeded(), eq(variables['IsPullRequestBuild'], 'false'))
Expand Down Expand Up @@ -138,6 +148,16 @@ stages:
appCenterServiceConnectionName: $(AppCenterServiceConnection)
appCenterDistributionGroup: $(AppCenterDistributionGroup)

# MOBSF SECURITY SCAN PRODUCTION
- stage: Security_Scan_Build_Production
dependsOn: Build_Production
jobs:
- template: stage-security-scan.yml
parameters:
applicationEnvironment: Production
enableIosSecurityScan: true
enableAndroidSecurityScan: true

- stage: AppStore
condition: and(succeeded(), eq(variables['IsPullRequestBuild'], 'false'))
dependsOn: Build_Production
Expand Down
34 changes: 34 additions & 0 deletions build/stage-security-scan.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
parameters:
- name: applicationEnvironment
type: string
default: ''
- name: enableIosSecurityScan
type: boolean
default: false
- name: enableAndroidSecurityScan
type: boolean
default: false

jobs:
- job: OnLinux_iOS_SecurityScan
condition: eq(${{parameters.enableIosSecurityScan}}, true)
dependsOn: []
pool:
vmImage: $(ubuntuHostedAgentImage)
steps:
- template: templates/mobsf-ios-scan.yml
parameters:
mobSfApiKey: $(mobSfApiKey)
artifactName: '$(iOSArtifactName)_${{ parameters.applicationEnvironment }}'

- job: OnLinux_Android_SecurityScan
condition: eq(${{parameters.enableAndroidSecurityScan}}, true)
dependsOn: []
pool:
vmImage: $(ubuntuHostedAgentImage)
steps:
- template: templates/mobsf-android-scan.yml
parameters:
mobSfApiKey: $(mobSfApiKey)
artifactName: '$(AndroidArtifactName)_${{ parameters.applicationEnvironment }}'

6 changes: 3 additions & 3 deletions build/steps-build-ios.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ steps:
bannerVersionNumberText: '$(MajorMinorPatch)'

- task: FlutterBuild@0
displayName: Build Project for Release
displayName: Build Project for Release
inputs:
target: 'ios'
buildName: '$(MajorMinorPatch)'
Expand All @@ -103,7 +103,7 @@ steps:
condition: failed()

- task: Xcode@5
condition: and(succeeded(), eq(variables['IsPullRequestBuild'], 'false'))
condition: succeeded()
displayName: 'Xcode Archive iOS'
inputs:
actions: 'archive'
Expand All @@ -122,7 +122,7 @@ steps:
provisioningProfileName: '$(provisioningProfile.provisioningProfileName)'

- task: CopyFiles@2
condition: and(succeeded(), eq(variables['IsPullRequestBuild'], 'false'))
condition: succeeded()
displayName: 'Copy Binary Files'
inputs:
sourceFolder: '${{ parameters.pathToSrc }}/app'
Expand Down
143 changes: 143 additions & 0 deletions build/templates/mobsf-android-scan.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
parameters:
- name: mobSfApiKey
type: string
default: $(mobSfApiKey)
- name: artifactName
type: string
default: ''

steps:
- task: DownloadPipelineArtifact@1
inputs:
buildType: 'current'
downloadType: 'single'
artifactName: "${{parameters.artifactName}}"
downloadPath: '$(System.ArtifactsDirectory)'
condition: succeeded()

- task: DockerInstaller@0
displayName: 'Install Docker'
inputs:
dockerVersion: $(DockerVersion)
condition: succeeded()

- script: docker pull opensecurity/mobile-security-framework-mobsf:latest
displayName: 'Pull MobSF Docker Image'
condition: succeeded()

- script: docker run -d -it --rm -e MOBSF_API_KEY='${{parameters.mobSfApiKey}}' -e DATA_UPLOAD_MAX_MEMORY_SIZE=209715200 -p 8000:8000 opensecurity/mobile-security-framework-mobsf:latest
displayName: 'Run MobSF Docker Image'
condition: succeeded()

- script: ls -R "$(System.ArtifactsDirectory)"
displayName: 'List Downloaded Artifacts'

- task: PowerShell@2
displayName: 'Upload Android file to MobSF'
inputs:
targetType: 'inline'
script: |
$FILENAME = Get-ChildItem -Path "$(System.ArtifactsDirectory)/" -File | Select-Object -First 1 -ExpandProperty Name
Write-Host "Filename: $FILENAME"
$file = "$(System.ArtifactsDirectory)/$FILENAME"
Write-Host "Uploading file $file to MobSF..."
# Check if the server is up and running
$serverIsRunning = $false
$retryCount = 0
while (-not $serverIsRunning -and $retryCount -lt 10) {
$response = curl --url http://127.0.0.1:8000/api/v1/scans -H "Authorization: ${{parameters.mobSfApiKey}}"
if ($response.StatusCode -eq 200) {
Write-Host "MobSF server is up and running"
$serverIsRunning = $true
} else {
Write-Host "Waiting for the MobSF server to start..."
$retryCount++
Start-Sleep -Seconds 5
}
}
$uploadResponse = curl -X POST -F "file=@$file;type=application/octet-stream" http://127.0.0.1:8000/api/v1/upload -H "Authorization: ${{parameters.mobSfApiKey}}"
$uploadResponseJson = $uploadResponse | ConvertFrom-Json
$hash = $uploadResponseJson.hash
echo "##vso[task.setvariable variable=fileHash]$hash"
Write-Host "Uploaded file hash: $hash"
Write-Host "Android file uploaded to MobSF"
condition: succeeded()

- task: PowerShell@2
displayName: 'Run MobSF Scan'
inputs:
targetType: 'inline'
script: |
Write-Host "MobSF Scan started"
$hash = "$(fileHash)"
$scanUrl = "http://127.0.0.1:8000/api/v1/scan"
Write-Host "Scanning Uploaded file hash: $hash"
$headers = @{
"Authorization" = ${{parameters.mobSfApiKey}}
}
$scanBody = @{
"scan_type" = "$(aabFileExtension)"
"hash" = $hash # use the hash from the upload response
}
$response = Invoke-RestMethod -Uri $scanUrl -Method Post -Headers $headers -Body $scanBody
Write-Host "Scan completed"
condition: succeeded()

- task: PowerShell@2
displayName: 'Download MobSF PDF report'
inputs:
targetType: 'inline'
script: |
Write-Host "Downloading MobSF PDF report..."
$hash = "$(fileHash)"
Write-Host "File hash: $hash"
$reportUrl = "http://127.0.0.1:8000/api/v1/download_pdf"
$headers = @{
"Authorization" = "${{parameters.mobSfApiKey}}"
}
$reportBody = @{
"hash" = $hash # use the hash from the upload response
}
$directoryPath = "${{parameters.artifactName}}/Android"
if (!(Test-Path -Path $directoryPath)) {
New-Item -ItemType Directory -Path $directoryPath | Out-Null
}
$pdfFilePath = "$directoryPath/report.pdf"
Invoke-WebRequest -Uri $reportUrl -Method Post -Headers $headers -Body $reportBody -OutFile $pdfFilePath
Write-Host "PDF report downloaded to $pdfFilePath"
condition: succeeded()

- task: PowerShell@2
displayName: 'Download MobSF Json report'
inputs:
targetType: 'inline'
script: |
Write-Host "Downloading MobSF Json report..."
$hash = "$(fileHash)"
Write-Host "File hash: $hash"
$reportUrl = "http://127.0.0.1:8000/api/v1/report_json"
$headers = @{
"Authorization" = "${{parameters.mobSfApiKey}}"
}
$reportBody = @{
"hash" = $hash # use the hash from the upload response
}
$reportResponse = Invoke-RestMethod -Uri $reportUrl -Method Post -Headers $headers -Body $reportBody
Write-Host "Response: $reportResponse"
$jsonFilePath = "${{parameters.artifactName}}/Android/Report.json"
$reportResponse | ConvertTo-Json | Out-File -FilePath $jsonFilePath
Write-Host "JSON report downloaded to $jsonFilePath"
condition: succeeded()

- task: PublishBuildArtifacts@1
displayName: 'Publish Artifact'
inputs:
PathtoPublish: '${{parameters.artifactName}}/Android'
ArtifactName: ${{parameters.artifactName}}_Security_Reports
publishLocation: 'Container'

- task: PostBuildCleanup@3
displayName: 'Post-Build Cleanup: Cleanup files to keep build server clean!'
condition: always()
143 changes: 143 additions & 0 deletions build/templates/mobsf-ios-scan.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
parameters:
- name: mobSfApiKey
type: string
default: $(mobSfApiKey)
- name: artifactName
type: string
default: ''

steps:
- task: DownloadPipelineArtifact@1
inputs:
buildType: 'current'
downloadType: 'single'
artifactName: "${{parameters.artifactName}}"
downloadPath: '$(System.ArtifactsDirectory)'
condition: succeeded()

- task: DockerInstaller@0
displayName: 'Install Docker'
inputs:
dockerVersion: $(DockerVersion)
condition: succeeded()

- script: docker pull opensecurity/mobile-security-framework-mobsf:latest
displayName: 'Pull MobSF Docker Image'
condition: succeeded()

- script: docker run -d -it --rm -e MOBSF_API_KEY='${{parameters.mobSfApiKey}}' -e DATA_UPLOAD_MAX_MEMORY_SIZE=209715200 -p 8000:8000 opensecurity/mobile-security-framework-mobsf:latest
displayName: 'Run MobSF Docker Image'
condition: succeeded()

- script: ls -R "$(System.ArtifactsDirectory)"
displayName: 'List Downloaded Artifacts'

- task: PowerShell@2
displayName: 'Upload IPA file to MobSF'
inputs:
targetType: 'inline'
script: |
$FILENAME = Get-ChildItem -Path "$(System.ArtifactsDirectory)/" -File | Select-Object -First 1 -ExpandProperty Name
Write-Host "Filename: $FILENAME"
$file = "$(System.ArtifactsDirectory)/$FILENAME"
Write-Host "Uploading file $file to MobSF..."
# Check if the server is up and running
$serverIsRunning = $false
$retryCount = 0
while (-not $serverIsRunning -and $retryCount -lt 10) {
$response = curl --url http://127.0.0.1:8000/api/v1/scans -H "Authorization: ${{parameters.mobSfApiKey}}"
if ($response.StatusCode -eq 200) {
Write-Host "MobSF server is up and running"
$serverIsRunning = $true
} else {
Write-Host "Waiting for the MobSF server to start..."
$retryCount++
Start-Sleep -Seconds 5
}
}
$uploadResponse = curl -X POST -F "file=@$file;type=application/octet-stream" http://127.0.0.1:8000/api/v1/upload -H "Authorization: ${{parameters.mobSfApiKey}}"
$uploadResponseJson = $uploadResponse | ConvertFrom-Json
$hash = $uploadResponseJson.hash
echo "##vso[task.setvariable variable=fileHash]$hash"
Write-Host "Uploaded file hash: $hash"
Write-Host "IPA file uploaded to MobSF"
condition: succeeded()

- task: PowerShell@2
displayName: 'Run MobSF Scan'
inputs:
targetType: 'inline'
script: |
Write-Host "MobSF Scan started"
$hash = "$(fileHash)"
$scanUrl = "http://127.0.0.1:8000/api/v1/scan"
Write-Host "Scanning Uploaded file hash: $hash"
$headers = @{
"Authorization" = ${{parameters.mobSfApiKey}}
}
$scanBody = @{
"scan_type" = "$(ipaFileExtension)"
"hash" = $hash # use the hash from the upload response
}
$response = Invoke-RestMethod -Uri $scanUrl -Method Post -Headers $headers -Body $scanBody
Write-Host "Scan completed"
condition: succeeded()

- task: PowerShell@2
displayName: 'Download MobSF PDF report'
inputs:
targetType: 'inline'
script: |
Write-Host "Downloading MobSF PDF report..."
$hash = "$(fileHash)"
Write-Host "File hash: $hash"
$reportUrl = "http://127.0.0.1:8000/api/v1/download_pdf"
$headers = @{
"Authorization" = "${{parameters.mobSfApiKey}}"
}
$reportBody = @{
"hash" = $hash # use the hash from the upload response
}
$directoryPath = "${{parameters.artifactName}}/ios"
if (!(Test-Path -Path $directoryPath)) {
New-Item -ItemType Directory -Path $directoryPath | Out-Null
}
$pdfFilePath = "$directoryPath/report.pdf"
Invoke-WebRequest -Uri $reportUrl -Method Post -Headers $headers -Body $reportBody -OutFile $pdfFilePath
Write-Host "PDF report downloaded to $pdfFilePath"
condition: succeeded()

- task: PowerShell@2
displayName: 'Download MobSF Json report'
inputs:
targetType: 'inline'
script: |
Write-Host "Downloading MobSF Json report..."
$hash = "$(fileHash)"
Write-Host "File hash: $hash"
$reportUrl = "http://127.0.0.1:8000/api/v1/report_json"
$headers = @{
"Authorization" = "${{parameters.mobSfApiKey}}"
}
$reportBody = @{
"hash" = $hash # use the hash from the upload response
}
$reportResponse = Invoke-RestMethod -Uri $reportUrl -Method Post -Headers $headers -Body $reportBody
Write-Host "Response: $reportResponse"
$jsonFilePath = "${{parameters.artifactName}}/ios/Report.json"
$reportResponse | ConvertTo-Json | Out-File -FilePath $jsonFilePath
Write-Host "JSON report downloaded to $jsonFilePath"
condition: succeeded()

- task: PublishBuildArtifacts@1
displayName: 'Publish Artifact'
inputs:
PathtoPublish: '${{parameters.artifactName}}/ios'
ArtifactName: ${{parameters.artifactName}}_Security_Reports
publishLocation: 'Container'

- task: PostBuildCleanup@3
displayName: 'Post-Build Cleanup: Cleanup files to keep build server clean!'
condition: always()
Loading

0 comments on commit 4379aa3

Please sign in to comment.