Skip to content

Commit

Permalink
Merge branch 'main' into feat/oidc-uai-env
Browse files Browse the repository at this point in the history
  • Loading branch information
eriqua authored Jul 22, 2024
2 parents d340070 + e247d3f commit 1e9fb02
Show file tree
Hide file tree
Showing 13 changed files with 792 additions and 24 deletions.
100 changes: 100 additions & 0 deletions .github/workflows/platform.ci-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
name: ".Platform - Run CI tests"

on:
workflow_dispatch:
inputs:
testFileRegex:
type: string
description: "The regex of the test file(s) to run"
required: false
default: '.*'
push:
branches:
- main
paths:
- ".github/workflows/platform.ci-tests.yml"
- "avm/utilities/**"
- "!*/**/README.md"
schedule:
- cron: "0 0 * * Sun" # Every Sunday

env:
workflowPath: ".github/workflows/platform.ci-tests.yml"


jobs:
###########################
# Initialize pipeline #
###########################
job_initialize_pipeline:
runs-on: ubuntu-latest
name: "Initialize pipeline"
steps:
- name: "Checkout"
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: "Set input parameters to output variables"
id: get-workflow-param
uses: ./.github/actions/templates/avm-getWorkflowInput
with:
workflowPath: "${{ env.workflowPath}}"
outputs:
workflowInput: ${{ steps.get-workflow-param.outputs.workflowInput }}

###############
# Removal #
###############
job_run_tests:
runs-on: ubuntu-20.04
name: "Run CI tests"
needs:
- job_initialize_pipeline
steps:
- name: "Checkout"
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set environment
uses: ./.github/actions/templates/avm-setEnvironment

- name: Run CI tests
id: pester_run_step
uses: azure/powershell@v2
with:
inlineScript: |
# Load used functions
. (Join-Path $env:GITHUB_WORKSPACE 'avm' 'utilities' 'tests' 'Test-CI.ps1')
$functionInput = @{
RepoRootPath = $env:GITHUB_WORKSPACE
BranchName = $env:GITHUB_REF
GitHubRepository = $env:GITHUB_REPOSITORY
TestFileRegex = '${{ (fromJson(needs.job_initialize_pipeline.outputs.workflowInput)).testFileRegex }}'
}
Write-Verbose "Invoke task with" -Verbose
Write-Verbose ($functionInput | ConvertTo-Json | Out-String) -Verbose
$outputsFilePath = Test-CI @functionInput
Write-Output ('{0}={1}' -f 'formattedPesterResultsPath', $outputsFilePath) >> $env:GITHUB_OUTPUT
azPSVersion: "latest"

- name: "Output to GitHub job summaries"
if: always()
shell: pwsh
run: |
# Grouping task logs
Write-Output '::group::Output to GitHub job summaries'
$mdPesterOutputFilePath = '${{ steps.pester_run_step.outputs.formattedPesterResultsPath }}'
if (-not (Test-Path $mdPesterOutputFilePath)) {
Write-Warning ('Input file [{0}] not found. Please check if the previous task threw an error and try again.' -f $mdPesterOutputFilePath)
} else {
Get-Content $mdPesterOutputFilePath >> $env:GITHUB_STEP_SUMMARY
Write-Verbose ('Successfully printed out file [{0}] to Job Summaries' -f $mdPesterOutputFilePath) -Verbose
}
Write-Output '::endgroup::'
4 changes: 2 additions & 2 deletions .github/workflows/platform.ossf-scorecard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
persist-credentials: false

- name: "Run analysis"
uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1
uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # v2.3.3
with:
results_file: results.sarif
results_format: sarif
Expand Down Expand Up @@ -68,6 +68,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard (optional).
# Commenting out will disable upload of results to your repo's Code Scanning dashboard
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@4fa2a7953630fd2f3fb380f21be14ede0169dd4f # v3.25.12
uses: github/codeql-action/upload-sarif@2d790406f505036ef40ecba973cc774a50395aac # v3.25.13
with:
sarif_file: results.sarif
78 changes: 78 additions & 0 deletions avm/res/app/container-app/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,8 @@ module containerApp 'br/public:avm/res/app/container-app:<version>' = {
| Parameter | Type | Description |
| :-- | :-- | :-- |
| [`activeRevisionsMode`](#parameter-activerevisionsmode) | string | Controls how active revisions are handled for the Container app. |
| [`clientCertificateMode`](#parameter-clientcertificatemode) | string | Client certificate mode for mTLS. |
| [`corsPolicy`](#parameter-corspolicy) | object | Object userd to configure CORS policy. |
| [`customDomains`](#parameter-customdomains) | array | Custom domain bindings for Container App hostnames. |
| [`dapr`](#parameter-dapr) | object | Dapr configuration for the Container App. |
| [`disableIngress`](#parameter-disableingress) | bool | Bool to disable all ingress traffic for the container app. |
Expand Down Expand Up @@ -940,6 +942,82 @@ Controls how active revisions are handled for the Container app.
]
```

### Parameter: `clientCertificateMode`

Client certificate mode for mTLS.

- Required: No
- Type: string
- Default: `'ignore'`
- Allowed:
```Bicep
[
'accept'
'ignore'
'require'
]
```

### Parameter: `corsPolicy`

Object userd to configure CORS policy.

- Required: No
- Type: object

**Optional parameters**

| Parameter | Type | Description |
| :-- | :-- | :-- |
| [`allowCredentials`](#parameter-corspolicyallowcredentials) | bool | Switch to determine whether the resource allows credentials. |
| [`allowedHeaders`](#parameter-corspolicyallowedheaders) | array | Specifies the content for the access-control-allow-headers header. |
| [`allowedMethods`](#parameter-corspolicyallowedmethods) | array | Specifies the content for the access-control-allow-methods header. |
| [`allowedOrigins`](#parameter-corspolicyallowedorigins) | array | Specifies the content for the access-control-allow-origins header. |
| [`exposeHeaders`](#parameter-corspolicyexposeheaders) | array | Specifies the content for the access-control-expose-headers header. |
| [`maxAge`](#parameter-corspolicymaxage) | int | Specifies the content for the access-control-max-age header. |

### Parameter: `corsPolicy.allowCredentials`

Switch to determine whether the resource allows credentials.

- Required: No
- Type: bool

### Parameter: `corsPolicy.allowedHeaders`

Specifies the content for the access-control-allow-headers header.

- Required: No
- Type: array

### Parameter: `corsPolicy.allowedMethods`

Specifies the content for the access-control-allow-methods header.

- Required: No
- Type: array

### Parameter: `corsPolicy.allowedOrigins`

Specifies the content for the access-control-allow-origins header.

- Required: No
- Type: array

### Parameter: `corsPolicy.exposeHeaders`

Specifies the content for the access-control-expose-headers header.

- Required: No
- Type: array

### Parameter: `corsPolicy.maxAge`

Specifies the content for the access-control-max-age header.

- Required: No
- Type: int

### Parameter: `customDomains`

Custom domain bindings for Container App hostnames.
Expand Down
43 changes: 41 additions & 2 deletions avm/res/app/container-app/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,17 @@ param disableIngress bool = false
@description('Optional. Bool indicating if the App exposes an external HTTP endpoint.')
param ingressExternal bool = true

@allowed([
'accept'
'ignore'
'require'
])
@description('Optional. Client certificate mode for mTLS.')
param clientCertificateMode string = 'ignore'

@description('Optional. Object userd to configure CORS policy.')
param corsPolicy corsPolicyType

@allowed([
'none'
'sticky'
Expand Down Expand Up @@ -186,6 +197,15 @@ resource containerApp 'Microsoft.App/containerApps@2023-05-01' = {
ingress: disableIngress ? null : {
allowInsecure: ingressAllowInsecure
customDomains: !empty(customDomains) ? customDomains : null
corsPolicy: corsPolicy != null ? {
allowCredentials: corsPolicy.?allowCredentials ?? false
allowedHeaders: corsPolicy.?allowedHeaders ?? []
allowedMethods: corsPolicy.?allowedMethods ?? []
allowedOrigins: corsPolicy.?allowedOrigins ?? []
exposeHeaders: corsPolicy.?exposeHeaders ?? []
maxAge: corsPolicy.?maxAge
} : null
clientCertificateMode: clientCertificateMode
exposedPort: exposedPort
external: ingressExternal
ipSecurityRestrictions: !empty(ipSecurityRestrictions) ? ipSecurityRestrictions : null
Expand Down Expand Up @@ -233,8 +253,7 @@ resource containerApp_lock 'Microsoft.Authorization/locks@2020-05-01' = if (!emp
scope: containerApp
}

resource containerApp_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [
for (roleAssignment, index) in (roleAssignments ?? []): {
resource containerApp_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ for (roleAssignment, index) in (roleAssignments ?? []): {
name: guid(containerApp.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName)
properties: {
roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName)
Expand Down Expand Up @@ -390,6 +409,26 @@ type containerAppProbe = {
type: ('Liveness' | 'Startup' | 'Readiness')?
}

type corsPolicyType = {
@description('Optional. Switch to determine whether the resource allows credentials.')
allowCredentials: bool?

@description('Optional. Specifies the content for the access-control-allow-headers header.')
allowedHeaders: string[]?

@description('Optional. Specifies the content for the access-control-allow-methods header.')
allowedMethods: string[]?

@description('Optional. Specifies the content for the access-control-allow-origins header.')
allowedOrigins: string[]?

@description('Optional. Specifies the content for the access-control-expose-headers header.')
exposeHeaders: string[]?

@description('Optional. Specifies the content for the access-control-max-age header.')
maxAge: int?
}?

type containerAppProbeHttpGet = {
@description('Optional. Host name to connect to. Defaults to the pod IP.')
host: string?
Expand Down
84 changes: 81 additions & 3 deletions avm/res/app/container-app/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
"metadata": {
"_generator": {
"name": "bicep",
"version": "0.28.1.47646",
"templateHash": "17800459642895019722"
"version": "0.29.45.22436",
"templateHash": "14209173975768378721"
},
"name": "Container Apps",
"description": "This module deploys a Container App.",
Expand Down Expand Up @@ -309,6 +309,66 @@
}
}
},
"corsPolicyType": {
"type": "object",
"properties": {
"allowCredentials": {
"type": "bool",
"nullable": true,
"metadata": {
"description": "Optional. Switch to determine whether the resource allows credentials."
}
},
"allowedHeaders": {
"type": "array",
"items": {
"type": "string"
},
"nullable": true,
"metadata": {
"description": "Optional. Specifies the content for the access-control-allow-headers header."
}
},
"allowedMethods": {
"type": "array",
"items": {
"type": "string"
},
"nullable": true,
"metadata": {
"description": "Optional. Specifies the content for the access-control-allow-methods header."
}
},
"allowedOrigins": {
"type": "array",
"items": {
"type": "string"
},
"nullable": true,
"metadata": {
"description": "Optional. Specifies the content for the access-control-allow-origins header."
}
},
"exposeHeaders": {
"type": "array",
"items": {
"type": "string"
},
"nullable": true,
"metadata": {
"description": "Optional. Specifies the content for the access-control-expose-headers header."
}
},
"maxAge": {
"type": "int",
"nullable": true,
"metadata": {
"description": "Optional. Specifies the content for the access-control-max-age header."
}
}
},
"nullable": true
},
"containerAppProbeHttpGet": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -444,6 +504,24 @@
"description": "Optional. Bool indicating if the App exposes an external HTTP endpoint."
}
},
"clientCertificateMode": {
"type": "string",
"defaultValue": "ignore",
"allowedValues": [
"accept",
"ignore",
"require"
],
"metadata": {
"description": "Optional. Client certificate mode for mTLS."
}
},
"corsPolicy": {
"$ref": "#/definitions/corsPolicyType",
"metadata": {
"description": "Optional. Object userd to configure CORS policy."
}
},
"stickySessionsAffinity": {
"type": "string",
"defaultValue": "none",
Expand Down Expand Up @@ -713,7 +791,7 @@
"configuration": {
"activeRevisionsMode": "[parameters('activeRevisionsMode')]",
"dapr": "[if(not(empty(parameters('dapr'))), parameters('dapr'), null())]",
"ingress": "[if(parameters('disableIngress'), null(), createObject('allowInsecure', parameters('ingressAllowInsecure'), 'customDomains', if(not(empty(parameters('customDomains'))), parameters('customDomains'), null()), 'exposedPort', parameters('exposedPort'), 'external', parameters('ingressExternal'), 'ipSecurityRestrictions', if(not(empty(parameters('ipSecurityRestrictions'))), parameters('ipSecurityRestrictions'), null()), 'targetPort', parameters('ingressTargetPort'), 'stickySessions', createObject('affinity', parameters('stickySessionsAffinity')), 'traffic', createArray(createObject('label', parameters('trafficLabel'), 'latestRevision', parameters('trafficLatestRevision'), 'revisionName', parameters('trafficRevisionName'), 'weight', parameters('trafficWeight'))), 'transport', parameters('ingressTransport')))]",
"ingress": "[if(parameters('disableIngress'), null(), createObject('allowInsecure', parameters('ingressAllowInsecure'), 'customDomains', if(not(empty(parameters('customDomains'))), parameters('customDomains'), null()), 'corsPolicy', if(not(equals(parameters('corsPolicy'), null())), createObject('allowCredentials', coalesce(tryGet(parameters('corsPolicy'), 'allowCredentials'), false()), 'allowedHeaders', coalesce(tryGet(parameters('corsPolicy'), 'allowedHeaders'), createArray()), 'allowedMethods', coalesce(tryGet(parameters('corsPolicy'), 'allowedMethods'), createArray()), 'allowedOrigins', coalesce(tryGet(parameters('corsPolicy'), 'allowedOrigins'), createArray()), 'exposeHeaders', coalesce(tryGet(parameters('corsPolicy'), 'exposeHeaders'), createArray()), 'maxAge', tryGet(parameters('corsPolicy'), 'maxAge')), null()), 'clientCertificateMode', parameters('clientCertificateMode'), 'exposedPort', parameters('exposedPort'), 'external', parameters('ingressExternal'), 'ipSecurityRestrictions', if(not(empty(parameters('ipSecurityRestrictions'))), parameters('ipSecurityRestrictions'), null()), 'targetPort', parameters('ingressTargetPort'), 'stickySessions', createObject('affinity', parameters('stickySessionsAffinity')), 'traffic', createArray(createObject('label', parameters('trafficLabel'), 'latestRevision', parameters('trafficLatestRevision'), 'revisionName', parameters('trafficRevisionName'), 'weight', parameters('trafficWeight'))), 'transport', parameters('ingressTransport')))]",
"maxInactiveRevisions": "[parameters('maxInactiveRevisions')]",
"registries": "[if(not(empty(parameters('registries'))), parameters('registries'), null())]",
"secrets": "[variables('secretList')]"
Expand Down
Loading

0 comments on commit 1e9fb02

Please sign in to comment.