Skip to content

Commit

Permalink
added cloudflare config script
Browse files Browse the repository at this point in the history
  • Loading branch information
christian bellee authored and christian bellee committed Dec 31, 2024
1 parent e2afcd1 commit cc66a02
Show file tree
Hide file tree
Showing 8 changed files with 198 additions and 25 deletions.
20 changes: 19 additions & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ env:
RESIZE_API_NAME: 'resize'
RESIZE_API_PORT: 8080
VERSION: 1.0.0
CLOUDFLARE_ZONE_ID: 'b553a0e598bd23879036daf46b81cbb3'
CLOUDFLARE_EMAIL: '[email protected]'
CLOUDFLARE_API_KEY: 'cloudflare_api_key'

jobs:
deploy-rg-job:
Expand Down Expand Up @@ -121,6 +124,17 @@ jobs:
id: checkout-code
uses: actions/checkout@main

- name: create storage account
uses: azure/CLI@v2
with:
azcliversion: 2.67.0
inlineScript: |
az deployment group create \
--name deploy-infra \
--resource-group ${{ needs.deploy-rg-job.outputs.rgName}} \
--template-file ./modules/stor.bicep \
--parameters
- name: login-azure
id: login-azure
uses: azure/login@v2
Expand All @@ -142,4 +156,8 @@ jobs:
--parameters resizeApiContainerImage=${{ needs.deploy-rg-job.outputs.resizeApiImage }} \
--parameters ghcrPullToken=${{ secrets.PAT_TOKEN }} \
--parameters ghcrName='ghcr.io' \
--parameters githubUsername=${{ github.actor }}
--parameters githubUsername=${{ github.actor }} \
--parameters cNameRecord=${{ vars.CNAME }} \
--parameters zoneName=${{ vars.ZONE_NAME }} \
--parameters cloudFlareApiToken=${{ secrets.CLOUDFLARE_API_TOKEN }} \
--parameters cloudFlareZoneId=${{ secrets.CLOUDFLARE_ZONE_ID }}
31 changes: 30 additions & 1 deletion api/cmd/photo/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ var (
)

func main() {
corsString := utils.GetEnvValue("CORS_ORIGINS", "http://localhost:5173,https://gallery.bellee.net,https://photos.bellee.net")
corsString := utils.GetEnvValue("CORS_ORIGINS", "http://localhost:5173,https://gallery.bellee.net,https://photos.bellee.net,https://photos.bellee.net")
corsOrigins := strings.Split(corsString, ",")
slog.Info("cors origins", "origins", corsOrigins)

Expand Down Expand Up @@ -404,15 +404,44 @@ func collectionHandler(client *azblob.Client, storageUrl string) http.HandlerFun
return func(w http.ResponseWriter, r *http.Request) {

// get photos with matching collection tags
var filteredBlobs []models.Blob

query := fmt.Sprintf("@container='%s' and collectionImage='true'", imagesContainerName)
slog.Info("query", "query", query)
filteredBlobs, err := queryBlobsByTags(client, storageUrl, query)
if err != nil {
slog.Error("Error getting blobs by tags", "error", err)
}

if len(filteredBlobs) <= 0 {
// try a query without the collectionImage tag
slog.Error("no collection images found, trying query without 'collectionImage' & will set a default placeholder collectionImage", "query", query)

query := fmt.Sprintf("@container='%s'", imagesContainerName)
filteredBlobs, err := queryBlobsByTags(client, storageUrl, query)
if err != nil {
slog.Error("Error getting blobs by tags", "error", err)
}

if len(filteredBlobs) <= 0 || filteredBlobs == nil {
slog.Error("no collection images found", "query", query)
http.Error(w, "No collection images found", http.StatusNotFound)
} else {
// set the first image as the collection image & write the tag back to the blob
filteredBlobs[0].Tags["collectionImage"] = "true"
err = utils.SetBlobTags(client, filteredBlobs[0].Name, imagesContainerName, storageUrl, filteredBlobs[0].Tags)
if err != nil {
slog.Error("error setting collectionImage tag", "error", err)
}
}
}

photos := []models.Photo{}

if filteredBlobs == nil || len(filteredBlobs) <= 0 {
http.Error(w, "No collection images found", http.StatusNotFound)
}

for _, r := range filteredBlobs {
slog.Info("Filtered Blobs", "Name", r.Name, "Metadata", r.MetaData, "Tags", r.Tags, "Path", r.Path)
width, err := strconv.ParseInt(r.MetaData["Width"], 10, 32)
Expand Down
72 changes: 72 additions & 0 deletions cloudflare.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
param(
[string]
$cloudFlareApiToken,
[string]
$cloudFlareZoneId,
[string]
$storageAccountWebEndpoint,
[string]
$cName
)

# Add CNAME DNS Record
$uri = "https://api.cloudflare.com/client/v4/zones/$cloudFlareZoneId/dns_records"

$params = @{
Uri = $uri
Headers = @{"Authorization" = "Bearer $cloudFlareApiToken"; "Content-Type" = "application/json" }
Method = 'POST'
Body =
@"
{
"comment": "CNAME record",
"content": "$storageAccountWebEndpoint",
"name": "$cName",
"proxied": true,
"ttl": 3600,
"type": "CNAME"
}
"@
}

try {
$resp = Invoke-WebRequest @params -ErrorAction Stop
if ($resp.StatusCode -ne 200) {
throw "Failed to add DNS Record. Code: $($resp.StatusCode) Desc: $($resp.StatusDescription)"
}
else {
Write-Output "DNS Record added successfully"
}
}
catch {
Write-Error "Failed to add DNS Record. $($_.Exception.Message)"
}

# Add Cloud Connector Rule
$uri = "https://api.cloudflare.com/client/v4/zones/$cloudFlareZoneId/cloud_connector/rules";

$params = @{
Uri = $uri
Headers = @{"Authorization" = "Bearer $cloudFlareApiToken"; "Content-Type" = "application/json" }
Method = 'PUT'
Body =
@"
[
{
"enabled": true,
"expression": "(http.request.full_uri wildcard \u0022\u0022)",
"provider": "azure_storage",
"description": "Connect to Azure storage container",
"parameters": {"host": "$storageAccountWebEndpoint"}
}
]
"@
}

$resp = Invoke-WebRequest @params
if ($resp.StatusCode -ne 200) {
throw "Failed to add Cloud Connector rule. Code: $($resp.StatusCode) Desc: $($resp.StatusDescription)"
}
else {
Write-Output "Cloud Connector rule added successfully"
}
2 changes: 1 addition & 1 deletion delete_images.sh
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
STORAGE_ACCOUNT_NAME='storhw3eyjlyy236y'
STORAGE_ACCOUNT_NAME='stor6aq2g56sfcosi'

az storage blob delete-batch --account-name $STORAGE_ACCOUNT_NAME --source uploads
az storage blob delete-batch --account-name $STORAGE_ACCOUNT_NAME --source images
2 changes: 1 addition & 1 deletion disable_sign_up_in_user_flow.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# go to https://developer.microsoft.com/en-us/graph-explorer
# go to https://developer.microsoft.com/en-us/graph/graph-explorer

# login to external EntraId tenant

Expand Down
49 changes: 30 additions & 19 deletions infra/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ param cNameRecord string = 'photo'
// param dnsResourceGroupName string = 'external-domain-rg'
param ghcrName string = 'ghcr.io'
param githubUsername string = 'cbellee'
param utcValue string = utcNow()
param cloudFlareZoneId string
param cloudFlareEmail string
param cloudFlareApiKey string
param cloudFlareApiToken string

@secure()
param ghcrPullToken string
Expand Down Expand Up @@ -576,31 +581,37 @@ module daprComponentUploadsStorageBlob 'modules/daprComponent.bicep' = {
]
}

/* module dnsModule 'modules/dns.bicep' = {
name: 'dnsModuleDeployment'
scope: resourceGroup(dnsResourceGroupName)
params: {
dnsZoneName: zoneName
cdnEndpoint: cdnEndpoint
cnameRecord: cName
resource enableCustomDomainAndCloudConnector 'Microsoft.Resources/deploymentScripts@2020-10-01' = {
name: 'enableCustomDomain'
location: resourceGroup().location
kind: 'AzurePowerShell'
properties: {
forceUpdateTag: utcValue
azPowerShellVersion: '7.0'
timeout: 'PT5M'
retentionInterval: 'PT1H'
storageAccountSettings: {
storageAccountName: storageAccountName
storageAccountKey: storage.outputs.key
}
primaryScriptUri: 'https://github.com/cbellee/photo-api/blob/e2afcd119e7ead8171a3c1d7538656145af7f67f/cloudflare.ps1'
arguments: '-cloudFlareApiToken ${cloudFlareApiToken} -storageAccountWebEndpoint ${storage.outputs.webEndpoint} -cloudFlareZoneId ${cloudFlareZoneId} -cName ${cNameRecord}'
}
}

module cdnModule 'modules/cdn.bicep' = {
name: 'cdnModuleDeployment'
module storageCustomDomain './modules/stor.bicep' = {
name: 'StorageCustomDomainDeployment'
params: {
cdnEndpoint: cdnEndpoint
cnameRecord: cName
dnsZoneName: zoneName
origin: storage.outputs.webEndpoint
storageAccountName: storage.outputs.name
storageAccountKey: storageKey
kind: 'StorageV2'
location: resourceGroup().location
name: storageAccountName
tags: tags
containers: containers
sku: 'Standard_LRS'
customDomainName: cName
deployCustomDomain: true
}
dependsOn: [
dnsModule
]
}
*/

output storageAccountName string = storage.outputs.name
output photoApiEndpoint string = photoApi.properties.configuration.ingress.fqdn
Expand Down
4 changes: 2 additions & 2 deletions infra/modules/stor.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ param isDefaultToOAuthAuthentication bool = false
param isAllowSharedAccessKey bool = true
param utcValue string = utcNow()
param customDomainName string
param deployCustomDomain bool = false

@allowed([
'Storage'
Expand Down Expand Up @@ -53,8 +54,7 @@ resource storage 'Microsoft.Storage/storageAccounts@2023-05-01' = {
supportsHttpsTrafficOnly: isSupportHttpsTrafficOnly
allowSharedKeyAccess: isAllowSharedAccessKey
customDomain: {
name: customDomainName
useSubDomainName: false
name: deployCustomDomain ? customDomainName : ''
}
}
tags: tags
Expand Down
43 changes: 43 additions & 0 deletions test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
CLOUDFLARE_API_TOKEN=''
CLOUDFLARE_API_KEY=''
CLOUDFLARE_EMAIL=''
CLOUDFLARE_ZONE_ID=''
STORAGE_ACCOUNT_WEB_ENDPOINT='<storageAccountName>.z8.web.core.windows.net'
CNAME='photo'
ZONE_NAME='bellee.net'

curl --request POST "https://api.cloudflare.com/client/v4/zones/${CLOUDFLARE_ZONE_ID}/dns_records" \
-header 'Content-Type: application/json' \
-header "X-Auth-Email: ${CLOUDFLARE_EMAIL}" \
-header "X-Auth-Key: ${CLOUDFLARE_API_KEY}" \
-data \
"
{
\"comment\": \"CNAME record\", \
\"content\": \"$STORAGE_ACCOUNT_WEB_ENDPOINT\", \
\"name\": \"$CNAME\", \
\"proxied\": true, \
\"ttl\": 3600, \
\"type\": \"CNAME\"
}
"

curl --request PUT "https://api.cloudflare.com/client/v4/zones/${CLOUDFLARE_ZONE_ID}/cloud_connector/rules" \
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
--header "Content-Type: application/json" \
--data \
"
[
{
\"enabled\": true, \
\"expression\": \"(http.request.full_uri wildcard)\", \
\"provider\": \"azure_storage\", \
\"description\": \"Connect to Azure storage container\", \
\"parameters\": {\"host\": \"${STORAGE_ACCOUNT_WEB_ENDPOINT}\"}
}
]
"

curl -X GET "https://api.cloudflare.com/client/v4/user/tokens/verify" \
-H "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
-H "Content-Type:application/json"

0 comments on commit cc66a02

Please sign in to comment.