Skip to content

Commit

Permalink
feat(305172): add MobSF security scan on android build staging and prod
Browse files Browse the repository at this point in the history
  • Loading branch information
Arieldelossantos committed Jun 25, 2024
1 parent 567eae8 commit 97cf01b
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 0 deletions.
30 changes: 30 additions & 0 deletions build/azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,21 @@ stages:
applicationEnvironment: Staging
deploymentEnvironment: TestFlight

# MOBSF SECURITY SCAN STAGING
- stage: Security_Scan_Build_Staging
dependsOn: Build_Staging
jobs:
- template: stage-build-security-android.yml
parameters:
applicationEnvironment: Staging
androidKeyStoreFile: $(InternalKeystore)
androidVariableGroup: 'ApplicationTemplate.Distribution.Internal.Android'
firebaseJsonFile: $(InternalFirebaseJson)
firebaseOptionsDartFile: $(InternalFirebaseOptionsDart)
androidKeyPropertiesFile: $(InternalKeyProperties)
googleServicesJsonFile: $(InternalGoogleServicesJson)
enableSecurityScan: true

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

# MOBSF SECURITY SCAN PRODUCTION
- stage: Security_Scan_Build_Production
dependsOn: Build_Production
jobs:
- template: stage-build-security-android.yml
parameters:
applicationEnvironment: Production
androidKeyStoreFile: $(GooglePlayKeystore)
androidKeyPropertiesFile: $(GooglePlayKeyProperties)
androidVariableGroup: 'ApplicationTemplate.Distribution.GooglePlay'
firebaseJsonFile: $(FirebaseJson)
firebaseOptionsDartFile: $(FirebaseOptionsDart)
googleServicesJsonFile: $(GoogleServicesJson)
enableSecurityScan: true

- stage: AppStore
condition: and(succeeded(), eq(variables['IsPullRequestBuild'], 'false'))
dependsOn: Build_Production
Expand Down
43 changes: 43 additions & 0 deletions build/stage-build-security-android.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
parameters:
- name: applicationEnvironment
type: string
default: ''
- name: androidKeyStoreFile
type: string
default: ''
- name: androidVariableGroup
type: string
default: ''
- name: artifactName
type: string
default: ''
- name: pathToSrc
type: string
default: '$(Build.SourcesDirectory)/src'
- name: androidKeyPropertiesFile
type: string
default: ''
- name: projectName
type: string
default: '$(ProjectName)'
- name: firebaseJsonFile
type: string
- name: firebaseOptionsDartFile
type: string
- name: googleServicesJsonFile
type: string
- name: enableSecurityScan
type: boolean
default: false

jobs:
- job: OnLinux_Android_SecurityScan
condition: eq(${{parameters.enableSecurityScan}}, true)
dependsOn: []
pool:
vmImage: $(ubuntuHostedAgentImage)
steps:
- template: templates/mobsf-android-scan.yml
parameters:
mobSfApiKey: '8181'
artifactName: '$(AndroidArtifactName)_${{ parameters.applicationEnvironment }}'
6 changes: 6 additions & 0 deletions build/steps-build-android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ parameters:
type: string
- name: googleServicesJsonFile
type: string
- name: artifactName
type: string
default: ''
- name: applicationEnvironment
type: string
default: ''

steps:
#-if false
Expand Down
141 changes: 141 additions & 0 deletions build/templates/mobsf-android-scan.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
parameters:
- name: mobSfApiKey
type: string
default: '8181'
- 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: |
$file = "$(System.ArtifactsDirectory)/app-release.$(aabFileExtension)"
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()
6 changes: 6 additions & 0 deletions build/variables.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
InternalKeyProperties: com.nventive.internal.flutterapptemplate.key.properties # This is the internal key properties used for internal builds.
GooglePlayKeystore: com.nventive.flutterapptemplate.jks # This is the official keystore used for Google Play.
GooglePlayKeyProperties: com.nventive.flutterapptemplate.key.properties # This is the official key properties used for Google Play.
aabFileExtension: aab # This is the file extension for Android App Bundles.
apkFileExtension: apk # This is the file extension for Android APKs.
# iOS.
InternalProvisioningProfile: com.nventive.internal.flutterapptemplate.mobileprovision # This is the internal provisioning profile for internal builds.
InternalExportOptions: com.nventive.internal.flutterapptemplate.exportOptions.plist # This is the export options file for internal builds.
Expand Down Expand Up @@ -69,9 +71,13 @@
# Flutter version.
FlutterVersion: '3.22.1'

# Docker version.
DockerVersion: '25.0.5'

# Virtual machine images.
windowsHostedAgentImage: 'windows-2022'
macOSHostedAgentImage: 'macOS-13'
ubuntuHostedAgentImage: 'ubuntu-latest'

# Name of the folder where the artefacts will be placed. Variable used in build and release phases.
# We make seperate folders so that releases can each download only the folder they need.
Expand Down
2 changes: 2 additions & 0 deletions src/cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)

Prefix your items with `(Template)` if the change is about the template and not the resulting application.
## 0.19.5
- Configured MobSF security scan on Android for Stanging and Production builds

## 0.19.3
- Fix CI/CD artifact name for iOS.
Expand Down

0 comments on commit 97cf01b

Please sign in to comment.