diff --git a/.circleci/build-installer.bat b/.circleci/build-installer.bat new file mode 100644 index 0000000..91331a9 --- /dev/null +++ b/.circleci/build-installer.bat @@ -0,0 +1,3 @@ +for /f "tokens=1 delims=-" %%i in ("%CIRCLE_TAG%") do set "TAG=%%i.%WORKFLOW_NUM%" +for /f "tokens=1 delims=/" %%j in ("%CIRCLE_TAG%") do set "SEMVER=%%j" +tools\InnoSetup\ISCC.exe tools\powerbi.iss /Sbyparam=$p /DINFO_VERSION=%TAG% /DVERSION=%SEMVER% %* \ No newline at end of file diff --git a/.circleci/config.yml b/.circleci/config.yml index 7d12474..a90f5da 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,11 +5,34 @@ version: 2.1 orbs: win: circleci/windows@5.0 +commands: + setup_digicert: + description: Set up Digicert Keylocker certificate for code-signing + steps: + - run: + name: "Digicert Signing Manager Setup" + command: | + cd C:\ + curl.exe -X GET https://one.digicert.com/signingmanager/api-ui/v1/releases/smtools-windows-x64.msi/download -H "x-api-key:$env:SM_API_KEY" -o smtools-windows-x64.msi + msiexec.exe /i smtools-windows-x64.msi /quiet /qn | Wait-Process + - run: + name: Setup Digicert ONE Client Cert + command: | + cd C:\ + echo $env:SM_CLIENT_CERT_FILE_B64 > certificate.txt + certutil -decode certificate.txt certificate.p12 + - run: + name: Sync Certs + command: | + & $env:SSM\smksp_cert_sync.exe + jobs: build-connector: executor: name: win/default shell: powershell.exe + environment: + SSM: 'C:\Program Files\DigiCert\DigiCert One Signing Manager Tools' steps: - checkout - run: @@ -20,24 +43,35 @@ jobs: - run: name: "Build Data Connector" command: "msbuild Speckle.proj /restore /consoleloggerparameters:NoSummary /property:GenerateFullPaths=true" - # - run: - # name: Create Innosetup signing cert - # command: | - # echo $env:PFX_B64 > "tools\AEC Systems Ltd.txt" - # certutil -decode "tools\AEC Systems Ltd.txt" "tools\AEC Systems Ltd.pfx" - # - run: - # name: Create Signed PFX file - # command: .\tools\MakePQX\MakePQX.exe pack -mz bin/Speckle.mez -t bin/Speckle.pqx -c "tools\AEC Systems Ltd.pfx" -p $env:PFX_PSW - # - run: - # name: Build Installer - # command: tools\InnoSetup\ISCC.exe tools\powerbi.iss /Sbyparam=$p - # shell: cmd.exe #does not work in powershell + - run: + name: Create PQX file + command: .\tools\MakePQX\MakePQX.exe pack -mz bin/Speckle.mez -t bin/Speckle.pqx + - unless: # Build installers unsigned on non-tagged builds + condition: << pipeline.git.tag >> + steps: + - run: + name: Build Installer + shell: cmd.exe #does not work in powershell + environment: + WORKFLOW_NUM: << pipeline.number >> + CIRCLE_TAG: 2.0.999-beta/all + command: .circleci\build-installer.bat + - when: # Setup certificates and build installers signed for tagged builds + condition: << pipeline.git.tag >> + steps: + - setup_digicert + - run: + name: Build Installer + shell: cmd.exe #does not work in powershell + environment: + WORKFLOW_NUM: << pipeline.number >> + command: .circleci\build-installer.bat /DSIGN_INSTALLER /DCODE_SIGNING_CERT_FINGERPRINT=%SM_CODE_SIGNING_CERT_SHA1_HASH% - store_artifacts: path: ./bin - persist_to_workspace: root: ./ paths: - - bin/* + - bin/*.exe deploy-connector: docker: - image: cibuilds/github:0.13 @@ -47,27 +81,42 @@ jobs: - run: name: "Publish Release on GitHub" command: | - ghr -t ${GH_TOKEN} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} ${CIRCLE_TAG} ./bin/Speckle.mez + ghr -t ${GH_TOKEN} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} ${CIRCLE_TAG} ./bin/Speckle.pqx + deploy-connector-to-feed: + docker: + - image: mcr.microsoft.com/dotnet/sdk:6.0 + steps: + - attach_workspace: + at: ./ + - run: + name: Install Manager Feed CLI + command: dotnet tool install --global Speckle.Manager.Feed + - run: + name: Upload new version + command: | + TAG=$(if [ "${CIRCLE_TAG}" ]; then echo $CIRCLE_TAG; else echo "2.0.999"; fi;) + SEMVER=$(echo "$TAG" | sed -e 's/\/[a-zA-Z-]*//') + VER=$(echo "$SEMVER" | sed -e 's/-.*//') + VERSION=$(echo $VER.$WORKFLOW_NUM) + /root/.dotnet/tools/Speckle.Manager.Feed deploy -s powerbi -v ${SEMVER} -u https://releases.speckle.dev/installers/powerbi/powerbi-${SEMVER}.exe -o Win -a Any -f ./bin/powerbi-${SEMVER}.exe + environment: + WORKFLOW_NUM: << pipeline.number >> workflows: build: jobs: - build-connector: - context: innosetup + context: digicert-keylocker deploy: jobs: - build-connector: - filters: - branches: - ignore: /.*/ # For testing only: /ci\/.*/ - tags: - only: /^([0-9]+)\.([0-9]+)\.([0-9]+)(?:-\w{1,10})?$/ - context: innosetup - - deploy-connector: - filters: + filters: &deploy_filter branches: ignore: /.*/ # For testing only: /ci\/.*/ tags: only: /^([0-9]+)\.([0-9]+)\.([0-9]+)(?:-\w{1,10})?$/ + context: digicert-keylocker + - deploy-connector-to-feed: + filters: *deploy_filter requires: - build-connector - context: github-dev-bot + context: do-spaces-speckle-releases diff --git a/Speckle.query.pq b/Speckle.query.pq index 49bfa0d..eeae708 100644 --- a/Speckle.query.pq +++ b/Speckle.query.pq @@ -1,2 +1,7 @@ // Use this file to write queries to test your data connector -let result = Speckle.GetByUrl("https://app.speckle.systems/projects/e2988234fb/models/60b2300470@b1f31a351a") in result +let + result = Speckle.GetByUrl( + "https://app.speckle.systems/projects/e2988234fb/models/60b2300470@b1f31a351a,60b2300470" + ) +in + result diff --git a/tools/includes/code-signing.iss b/tools/includes/code-signing.iss new file mode 100644 index 0000000..cbb6004 --- /dev/null +++ b/tools/includes/code-signing.iss @@ -0,0 +1,7 @@ +#ifdef SIGN_INSTALLER + #ifdef CODE_SIGNING_CERT_FINGERPRINT + SignTool=byparam {#SourcePath}SignTool\signtool.exe sign /sha1 {#CODE_SIGNING_CERT_FINGERPRINT} /tr http://timestamp.digicert.com /td SHA512 /fd SHA512 $f + #else + #error "CODE_SIGNING_CERT_FINGERPRINT is not defined! Please provide the fingerprint of the certificate to use compile time define (i.e. /DCODE_SIGNING_CERT_FINGERPRINT=XXXXX) when invoking ISCC.exe" + #endif +#endif diff --git a/tools/custom-ui.iss b/tools/includes/custom-ui.iss similarity index 100% rename from tools/custom-ui.iss rename to tools/includes/custom-ui.iss diff --git a/tools/includes/registry-thumbprint-edit.iss b/tools/includes/registry-thumbprint-edit.iss new file mode 100644 index 0000000..7173436 --- /dev/null +++ b/tools/includes/registry-thumbprint-edit.iss @@ -0,0 +1,75 @@ +[Code] +function AddThumbPrintToRegistry(fingerprint: String): Boolean; +var + CurrentValues: TStringList; + RegData: string; +begin + CurrentValues:= TStringList.Create(); + if RegQueryMultiStringValue(HKLM, 'Software\Policies\Microsoft\Power BI Desktop', 'TrustedCertificateThumbprints', RegData) then + CurrentValues.Text:= RegData; + + if CurrentValues.IndexOf(fingerprint) = -1 then + begin + // If Thumbprint is not already added + CurrentValues.Add(fingerprint); + RegData:= CurrentValues.Text; + Result := RegWriteMultiStringvalue(HKLM, 'Software\Policies\Microsoft\Power BI Desktop', 'TrustedCertificateThumbprints', RegData); + end + else + Result := True; // Already exists + + CurrentValues.Free; +end; + +function DelThumbPrintFromRegistry(fingerprint: String): Boolean; +var + CurrentValues: TStringList; + Index: Integer; + RegData: string; +begin + Result:= True; + CurrentValues:= TStringList.Create(); + + if RegQueryMultiStringValue(HKLM, 'Software\Policies\Microsoft\Power BI Desktop', 'TrustedCertificateThumbprints', RegData) then + begin + CurrentValues.Text:= RegData; + Index := CurrentValues.IndexOf(fingerprint); + // If found, remove it + if Index <> -1 then + begin + CurrentValues.Delete(Index); + RegData:= CurrentValues.Text; + Result := RegWriteMultiStringvalue(HKLM, 'Software\Policies\Microsoft\Power BI Desktop', 'TrustedCertificateThumbprints', RegData); + end else begin + MsgBox('Failed to add thumbprint', mbError, MB_OK); + end; + end; + + CurrentValues.Free; +end; + +#ifdef CODE_SIGNING_CERT_FINGERPRINT + #define FINGERPRINT=CODE_SIGNING_CERT_FINGERPRINT +#else + #define FINGERPRINT=AppPublisher +#endif + +procedure CurStepChanged(CurStep: TSetupStep); +begin + if CurStep = ssInstall then + begin + // this is the installer + if not AddThumbPrintToRegistry('{#FINGERPRINT}') then + MsgBox('Failed to add thumbprint', mbError, MB_OK); + end; +end; + +procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep); +begin + if CurUninstallStep = usUninstall then + begin + // Remove thumbprint on uninstall + DelThumbPrintFromRegistry('{#FINGERPRINT}'); + end; +end; + diff --git a/tools/powerbi.iss b/tools/powerbi.iss index 5cd5164..91b5d6b 100644 --- a/tools/powerbi.iss +++ b/tools/powerbi.iss @@ -1,4 +1,4 @@ -#include "custom-ui.iss" +#include "includes\custom-ui.iss" #define AppName "Speckle for PowerBI (Data Connector)" #define Slug "powerbi" @@ -6,36 +6,37 @@ #define BasePath "..\" #define Bin BasePath + "bin\" -#define AppVersion "2.0.0" -#define AppInfoVersion "2.0.0.1234" +#ifndef Version + #define Version "2.0.999" +#endif + +#ifndef InfoVersion + #define InfoVersion "2.0.999.9999" +#endif + #define AppPublisher "Speckle" #define AppURL "https://speckle.systems" #define UninstallerFolder "{autoappdata}\Speckle\Uninstallers\" + Slug #define CustomConnectorFolder "{%USERPROFILE}\Documents\Power BI Desktop\Custom Connectors" -#define PFX_PSW GetEnv('PFX_PSW') [Setup] AppId={{6759e9e1-8c6b-4974-87c3-bb3c8b8ce619} ; Shouldn't need to update these AppName={#AppName} -AppVersion={#AppInfoVersion } -AppVerName={#AppName} {#AppInfoVersion } +AppVersion={#Version } +AppVerName={#AppName} {#Version} AppPublisher={#AppPublisher} AppPublisherURL={#AppURL} AppSupportURL={#AppURL} AppUpdatesURL={#AppURL} -AppCopyright=Copyright (C) 2020-2022 AEC SYSTEMS LTD +AppCopyright=Copyright (C) 2020-2024 AEC SYSTEMS LTD DefaultDirName={#UninstallerFolder} -VersionInfoVersion={#AppVersion} -ChangesAssociations=yes +VersionInfoVersion={#InfoVersion} CloseApplications=false PrivilegesRequired=admin -OutputBaseFilename={#Slug} OutputDir={#Bin} -; Needed so that the rhino registry key is put in the right location -ArchitecturesInstallIn64BitMode=x64 - +OutputBaseFilename={#Slug}-{#Version} ; UI WindowShowCaption=no WizardSizePercent=100,100 @@ -47,7 +48,8 @@ DisableProgramGroupPage=yes DisableWelcomePage=yes DisableFinishedPage=yes -;SignTool=byparam tools\SignTool\signtool.exe sign /f $qtools\AEC Systems Ltd.pfx$q /p {#PFX_PSW} /tr http://timestamp.digicert.com /td sha256 /fd sha256 $f + +#include "includes\code-signing.iss" [Languages] Name: "english"; MessagesFile: "compiler:Default.isl" @@ -55,5 +57,6 @@ Name: "english"; MessagesFile: "compiler:Default.isl" [Files] Source: "{#Bin}Speckle.pqx"; DestDir: "{#CustomConnectorFolder}"; -[Registry] -Root: HKLM; Subkey: "Software\Policies\Microsoft\Power BI Desktop"; ValueType: multisz; ValueName: "TrustedCertificateThumbprints"; ValueData: "4797ACC22464ED1CF9AFF4C09C2CCF4CF1873EFB"; Flags: uninsdeletekey +; TODO: Including the thumbprint in the registry will enable this running in higher security environments. +; Currently blocked because of MakePQX.exe not being ready to work with online CSP's like Digicert Keylocker. +; #include "includes\registry-thumbprint-edit.iss"