update
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
trigger:
|
||||
- main
|
||||
|
||||
name: 'ITD.Infra-Certificate-External.Sectigo'
|
||||
|
||||
variables:
|
||||
major: 0
|
||||
minor: 1
|
||||
patch: $(Build.BuildID)
|
||||
buildVer: $(major).$(minor).$(Build.BuildID)
|
||||
|
||||
pool: itdwinautop1
|
||||
|
||||
stages:
|
||||
- stage: Build
|
||||
jobs:
|
||||
- job: Build
|
||||
steps:
|
||||
- task: PowerShell@2
|
||||
inputs:
|
||||
filePath: '$(System.DefaultWorkingDirectory)/Build/build.ps1'
|
||||
- task: NuGetCommand@2
|
||||
inputs:
|
||||
command: 'pack'
|
||||
packagesToPack: '$(System.DefaultWorkingDirectory)/ITD.Infra-Certificate-External.Sectigo.nuspec'
|
||||
versioningScheme: byEnvVar
|
||||
versionEnvVar: buildVer
|
||||
buildProperties: 'VERSIONHERE=$(buildVer)'
|
||||
- task: PublishBuildArtifacts@1
|
||||
inputs:
|
||||
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
|
||||
ArtifactName: 'NuGetPackage'
|
||||
publishLocation: 'Container'
|
||||
- stage: Deploy
|
||||
jobs:
|
||||
- job: Deploy
|
||||
steps:
|
||||
- task: DownloadPipelineArtifact@2
|
||||
inputs:
|
||||
buildType: 'current'
|
||||
artifactName: 'NuGetPackage'
|
||||
itemPattern: '**'
|
||||
targetPath: '$(Pipeline.Workspace)'
|
||||
- task: NuGetCommand@2
|
||||
inputs:
|
||||
command: 'push'
|
||||
packagesToPush: '$(Pipeline.Workspace)/ITD.Infra-Certificate-External.Sectigo.$(major).$(minor).$(Build.BuildID).nupkg'
|
||||
nuGetFeedType: external
|
||||
publishFeedCredentials: 'ITD_PwshGallery'
|
||||
@@ -0,0 +1,17 @@
|
||||
$buildVersion = $env:BUILDVER
|
||||
$moduleName = 'ITD.Infra-Certificate-External.Sectigo'
|
||||
|
||||
$manifestPath = Join-Path -Path $env:SYSTEM_DEFAULTWORKINGDIRECTORY -ChildPath "$moduleName.psd1"
|
||||
$modulePath = Join-Path -Path $env:SYSTEM_DEFAULTWORKINGDIRECTORY -ChildPath "$moduleName.psm1"
|
||||
|
||||
## Update build version in manifest
|
||||
$manifestContent = Get-Content -Path $manifestPath -Raw
|
||||
$manifestContent = $manifestContent -replace '<ModuleVersion>', $buildVersion
|
||||
|
||||
## Update functions to export in manifest
|
||||
Import-Module $modulePath
|
||||
$funcStrings = (Get-Module ITD.Infra-Certificate-External.Sectigo).ExportedCommands.Values.Name
|
||||
$funcStrings = "'$($funcStrings -join "','")'"
|
||||
$manifestContent = $manifestContent -replace "<FunctionsToExport>", $funcStrings
|
||||
|
||||
$manifestContent | Set-Content -Path $manifestPath
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"AppConfig": {
|
||||
|
||||
"AuthBaseAPIUrl": {
|
||||
"Description": "API url for Sectigo - Authentication only",
|
||||
"Value": "https://auth.sso.sectigo.com"
|
||||
},
|
||||
|
||||
"BaseAPIUrl": {
|
||||
"Description": "API url for Sectigo - Calls",
|
||||
"Value": "https://admin.hard.sectigo.com"
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0"?>
|
||||
<package>
|
||||
<metadata>
|
||||
<id>ITD.Infra-Certificate-External.Sectigo</id>
|
||||
<version>$VERSIONHERE$</version>
|
||||
<authors>Freeman Peterson</authors>
|
||||
<description>Functions for Sectigo certificate enrollment and deployment</description>
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="**" exclude="**\.git\**;**\Build\**" />
|
||||
</files>
|
||||
</package>
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
#
|
||||
# Module manifest for module 'ITD.Infra-Certificate-External.Sectigo'
|
||||
#
|
||||
# Generated by: zmeier
|
||||
#
|
||||
# Generated on: 11/5/2025
|
||||
#
|
||||
|
||||
@{
|
||||
|
||||
# Script module or binary module file associated with this manifest.
|
||||
RootModule = 'ITD.Infra-Certificate-External.Sectigo.psm1'
|
||||
|
||||
# Version number of this module.
|
||||
ModuleVersion = '<ModuleVersion>'
|
||||
|
||||
# Supported PSEditions
|
||||
CompatiblePSEditions = 'Desktop', 'Core'
|
||||
|
||||
# ID used to uniquely identify this module
|
||||
GUID = '5c65f13f-9bde-40d3-97ce-aa9b37883db2'
|
||||
|
||||
# Author of this module
|
||||
Author = 'fjpeterson'
|
||||
|
||||
# Company or vendor of this module
|
||||
CompanyName = 'State of North Dakota'
|
||||
|
||||
# Copyright statement for this module
|
||||
Copyright = '(c) 2026 fjpeterson. All rights reserved.'
|
||||
|
||||
# Description of the functionality provided by this module
|
||||
Description = 'Functions for Sectigo certificate enrollment and deployment'
|
||||
|
||||
# Minimum version of the PowerShell engine required by this module
|
||||
# PowerShellVersion = ''
|
||||
|
||||
# Name of the PowerShell host required by this module
|
||||
# PowerShellHostName = ''
|
||||
|
||||
# Minimum version of the PowerShell host required by this module
|
||||
# PowerShellHostVersion = ''
|
||||
|
||||
# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
|
||||
# DotNetFrameworkVersion = ''
|
||||
|
||||
# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
|
||||
# ClrVersion = ''
|
||||
|
||||
# Processor architecture (None, X86, Amd64) required by this module
|
||||
# ProcessorArchitecture = ''
|
||||
|
||||
# Modules that must be imported into the global environment prior to importing this module
|
||||
# RequiredModules = @()
|
||||
|
||||
# Assemblies that must be loaded prior to importing this module
|
||||
# RequiredAssemblies = @()
|
||||
|
||||
# Script files (.ps1) that are run in the caller's environment prior to importing this module.
|
||||
# ScriptsToProcess = @()
|
||||
|
||||
# Type files (.ps1xml) to be loaded when importing this module
|
||||
# TypesToProcess = @()
|
||||
|
||||
# Format files (.ps1xml) to be loaded when importing this module
|
||||
# FormatsToProcess = @()
|
||||
|
||||
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
|
||||
# NestedModules = @()
|
||||
|
||||
# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
|
||||
FunctionsToExport = @(<FunctionsToExport>)
|
||||
|
||||
# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
|
||||
CmdletsToExport = @()
|
||||
|
||||
# Variables to export from this module
|
||||
VariablesToExport = '*'
|
||||
|
||||
# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
|
||||
AliasesToExport = @()
|
||||
|
||||
# DSC resources to export from this module
|
||||
# DscResourcesToExport = @()
|
||||
|
||||
# List of all modules packaged with this module
|
||||
# ModuleList = @()
|
||||
|
||||
# List of all files packaged with this module
|
||||
# FileList = @()
|
||||
|
||||
# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
|
||||
PrivateData = @{
|
||||
|
||||
PSData = @{
|
||||
|
||||
# Tags applied to this module. These help with module discovery in online galleries.
|
||||
# Tags = @()
|
||||
|
||||
# A URL to the license for this module.
|
||||
# LicenseUri = ''
|
||||
|
||||
# A URL to the main website for this project.
|
||||
# ProjectUri = ''
|
||||
|
||||
# A URL to an icon representing this module.
|
||||
# IconUri = ''
|
||||
|
||||
# ReleaseNotes of this module
|
||||
# ReleaseNotes = ''
|
||||
|
||||
# Prerelease string of this module
|
||||
# Prerelease = ''
|
||||
|
||||
# Flag to indicate whether the module requires explicit user acceptance for install/update/save
|
||||
# RequireLicenseAcceptance = $false
|
||||
|
||||
# External dependent modules of this module
|
||||
# ExternalModuleDependencies = @()
|
||||
|
||||
} # End of PSData hashtable
|
||||
|
||||
} # End of PrivateData hashtable
|
||||
|
||||
# HelpInfo URI of this module
|
||||
# HelpInfoURI = ''
|
||||
|
||||
# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
|
||||
# DefaultCommandPrefix = ''
|
||||
|
||||
}
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||
|
||||
#Get public and private function definition files.
|
||||
$Public = @( Get-ChildItem -Path $PSScriptRoot\Public\*.ps1 -ErrorAction SilentlyContinue )
|
||||
$Private = @( Get-ChildItem -Path $PSScriptRoot\Private\*.ps1 -ErrorAction SilentlyContinue )
|
||||
|
||||
#Dot source the files
|
||||
Foreach($import in @($Public + $Private))
|
||||
{
|
||||
Try
|
||||
{
|
||||
. $import.fullname
|
||||
}
|
||||
Catch
|
||||
{
|
||||
Write-Error -Message "Failed to import function $($import.fullname): $_"
|
||||
}
|
||||
}
|
||||
|
||||
# Here I might...
|
||||
# Read in or create an initial config file and variable
|
||||
# Export Public functions ($Public.BaseName) for WIP modules
|
||||
# Set variables visible to the module and its functions only
|
||||
|
||||
Export-ModuleMember -Function $Public.Basename
|
||||
@@ -0,0 +1,37 @@
|
||||
# Using configuration file for most of the settings
|
||||
$ConfigFile="${PSScriptRoot}/../Data/config.json"
|
||||
$Config=(Get-Content -Path $ConfigFile|ConvertFrom-Json).AppConfig
|
||||
|
||||
#Load Configuration File as Variables
|
||||
$ConfigVars=($Config | Get-Member -Membertype Noteproperty).Name
|
||||
ForEach ($ConfigVar in $ConfigVars) {
|
||||
Set-Variable -Name $ConfigVar -Value $Config.${ConfigVar}.Value
|
||||
}
|
||||
|
||||
#Remove temporary variables we don't need to reused thse
|
||||
Remove-Variable -Name Config,ConfigFile,ConfigVar,ConfigVars
|
||||
|
||||
$TimeZone=(timezone).id
|
||||
|
||||
# We need to declare the fields for syncing.
|
||||
$SyncFields = @("Admins", "AgencyName","App","City","Cluster","Environment","SRM_Request","SRM_Status","SupportHours","TeamLead","VLAN","VMHost" )
|
||||
$SNSyncFields=@("Environment","AgencyName")
|
||||
|
||||
#Default before set
|
||||
$VerbosePreference = "SilentlyContinue"
|
||||
$InformationPreference = "SilentlyContinue"
|
||||
$DebugPreference = "SilentlyContinue"
|
||||
|
||||
# Sets logging levels for cmdlets.
|
||||
Switch ($VerboseLevel) {
|
||||
0 { $VerbosePreference = "SilentlyContinue" }
|
||||
1 { $VerbosePreference = "Continue" }
|
||||
2 { $VerbosePreference = "Continue" ; $InformationPreference = "Continue" }
|
||||
3 { $VerbosePreference = "Continue" ; $InformationPreference = "Continue"; $DebugPreference = "Continue" }
|
||||
}
|
||||
|
||||
# Overrides email SNMPTO
|
||||
if ($TestMode -eq $True) {
|
||||
Write-Information "Test Mode - On"
|
||||
$SNMPTo = $TestModeAdmin
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
|
||||
#'x509' - for Certificate (w/ chain), PEM encoded,
|
||||
#'x509CO' - for Certificate only, PEM encoded,
|
||||
#'base64' - for PKCS#7, PEM encoded,
|
||||
#'bin' - for PKCS#7, 'x509IO' - for Root/Intermediate(s) only, PEM encoded,
|
||||
#'x509IOR' - for Intermediate(s)/Root only, PEM encoded,
|
||||
#'pem' - for Certificate (w/ chain), PEM encoded,
|
||||
#'pemco' - for Certificate only, PEM encoded,
|
||||
#'pemia' - for Certificate (w/ issuer after), PEM encoded,
|
||||
#'x509R' - for Certificate (w/ chain), PEM encoded.
|
||||
# base64 is default.
|
||||
|
||||
function Download-SectigoCertificate {
|
||||
[CmdletBinding(SupportsShouldProcess=$true)]
|
||||
param (
|
||||
[string]$ApiToken=$env:SectigoToken,
|
||||
[string]$CertRootPath="c:\certs",
|
||||
[ValidateSet('x509','x509CO','base64','bin','x509IOR','pem','pemco','pemia','x509R' )]
|
||||
[string]$Format="x509CO",
|
||||
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$OrderId
|
||||
)
|
||||
|
||||
if (-Not $ApiToken) {
|
||||
$ApiToken=Read-Host "ApiToken:"
|
||||
}
|
||||
. $PSScriptRoot\..\Private\Set-Onload.ps1
|
||||
|
||||
[string]$CollectUrl = "${BaseAPIUrl}/api/ssl/v1/collect/${OrderId}?format=${format}"
|
||||
|
||||
Write-Verbose -Verbose "CollectUrl: $CollectUrl"
|
||||
$headers = @{
|
||||
"Authorization" = "Bearer $ApiToken"
|
||||
"Content-Type" = "application/json" # <-- Cleaned up syntax
|
||||
}
|
||||
|
||||
# --- API Call ---
|
||||
Write-Verbose "Attempting to retrieve certificate for Order ID: $OrderId"
|
||||
|
||||
try {
|
||||
$response = Invoke-WebRequest -Uri $CollectUrl -Method Get -Headers $headers -UseBasicParsing -ErrorAction Stop
|
||||
} catch {
|
||||
Write-Error "API Request Failed: $($_.Exception.Message)"
|
||||
return $null
|
||||
}
|
||||
$OutPath = "${CertRootPath}\cert_${OrderId}.cer"
|
||||
|
||||
# --- Response Processing ---
|
||||
if ($response.StatusCode -eq 200) {
|
||||
Write-Verbose "Certificate successfully retrieved (Status 200)."
|
||||
|
||||
# 1. Get the Hex String
|
||||
# ASSUMPTION: The API returns the raw certificate Hex string in the response content.
|
||||
# If the API returns JSON, you must use 'ConvertFrom-Json' first to extract the hex property.
|
||||
$decimalNumbersString = $response.Content
|
||||
|
||||
$numberStrings = $decimalNumbersString -split '\s+|,|\r?\n' | Where-Object { $_ }
|
||||
|
||||
try {
|
||||
[byte[]]$bytes = $numberStrings | ForEach-Object { [int]$_ }
|
||||
} catch {
|
||||
Write-Error "Error converting numbers. Ensure all numbers are between 0 and 255."
|
||||
exit
|
||||
}
|
||||
|
||||
# Write the byte array to the binary file
|
||||
[System.IO.File]::WriteAllBytes($OutPath , $bytes)
|
||||
Get-ChildItem $OutPath|select fullname, LastWriteTime
|
||||
}
|
||||
}
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
Function Enroll-SectigoCertificateRequest {
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[string]$ApiToken=$env:SectigoToken,
|
||||
[int]$OrgId=8091, # 8091 friendly label is "Information Technology Department - Windows"
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$subjAltNames,
|
||||
[ValidateSet('IIS','IIS_OLD','IBM','LINUX','Apache','Tomcat')]
|
||||
[string]$Type="IIS",
|
||||
[string]$comment = "",
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$dcvEmail,
|
||||
[Parameter(Mandatory=$true)]
|
||||
[ValidateSet('ECC',"RSA")]
|
||||
[string]$KeyType,
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$Csr, # Replace with your Sectigo Organization ID
|
||||
[switch]$Test
|
||||
)
|
||||
if (-Not $ApiToken) {
|
||||
$ApiToken=Read-Host "ApiToken:"
|
||||
}
|
||||
|
||||
. $PSScriptRoot\..\Private\Set-Onload.ps1
|
||||
|
||||
[string]$RequestUrl= $BaseAPIUrl + "/api/ssl/v1/enroll"
|
||||
|
||||
Write-Verbose -Verbose "RequestUrl: $RequestUrl"
|
||||
#$CertType=2369
|
||||
|
||||
#If ($subjAltNames) {
|
||||
$CertType=2375
|
||||
#}
|
||||
|
||||
|
||||
$term=365
|
||||
# 7: IBM HTTP Server
|
||||
# 14: Microsoft IIS 5 or 6
|
||||
switch ($ServerType.ToLower()) {
|
||||
"iis" {
|
||||
$ServerTypeCode = 35
|
||||
}
|
||||
"iis_old" {
|
||||
$ServerTypeCode = 14
|
||||
}
|
||||
"ibm" {
|
||||
$ServerTypeCode = 7
|
||||
}
|
||||
"linux" {
|
||||
$ServerTypeCode = 'Linux'
|
||||
}
|
||||
"apache" {
|
||||
$ServerTypeCode = 2
|
||||
}
|
||||
"tomcat" {
|
||||
$ServerTypeCode = 12
|
||||
}
|
||||
default {
|
||||
Write-Warning "Unsupported server type: $ServerType. Please provide specific instructions for manual installation."
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ignorded for now
|
||||
# keySize = 2048,
|
||||
# keyParam = 2048,
|
||||
# algorithm = $KeyType
|
||||
# keyGenerationMethod = PK_AGENT
|
||||
|
||||
|
||||
$body = @{
|
||||
orgId = $OrgId
|
||||
subjAltNames = $subjAltNames
|
||||
certType = $CertType
|
||||
term = $term
|
||||
serverType = $ServerTypeCode
|
||||
comments = $comment
|
||||
csr = $csr
|
||||
externalRequester = $dcvEmail
|
||||
}
|
||||
|
||||
#$b2= @{
|
||||
# subjAltNames = $subjAltNames
|
||||
#}
|
||||
#
|
||||
#if ($subjAltNames) {
|
||||
# $body = $body + $b2
|
||||
#}
|
||||
|
||||
|
||||
|
||||
$b3=@{
|
||||
commonName = $commonName
|
||||
keySize = 2048
|
||||
keyParam = "2048"
|
||||
algorithm = "RSA"
|
||||
keyGenerationMethod = "PK_AGENT"
|
||||
}
|
||||
|
||||
$b4=@{
|
||||
commonName = $commonName
|
||||
keyParam = "secp256r1"
|
||||
algorithm = "ESS"
|
||||
keyGenerationMethod = "PK_AGENT"
|
||||
}
|
||||
|
||||
|
||||
|
||||
# $body = $body + $b2
|
||||
#If ($KeyType -eq "rsa") {
|
||||
# $body = $body + $b3
|
||||
#} else {
|
||||
# $body = $body + $b4
|
||||
#}
|
||||
|
||||
|
||||
|
||||
|
||||
If ($test) {
|
||||
Return
|
||||
}
|
||||
|
||||
# Convert the body to JSON
|
||||
$jsonBody = $body | ConvertTo-Json
|
||||
|
||||
Write-Host $jsonBody
|
||||
|
||||
# --- Set up Authentication Headers ---
|
||||
$headers = @{
|
||||
"Authorization" = "Bearer $ApiToken"
|
||||
"Content-Type" = "application/json"
|
||||
}
|
||||
|
||||
# --- Send the Request ---
|
||||
try {
|
||||
$response=Invoke-RestMethod -Uri $RequestUrl -Method POST -Headers $headers -Body $jsonBody -ContentType "application/json"
|
||||
|
||||
return $response
|
||||
}
|
||||
catch {
|
||||
Write-Error "Error during certificate enrollment: $($_.Exception.Message)"
|
||||
if ($_.Exception.Response) {
|
||||
$errorResponse = $_.Exception.Response.GetResponseStream()
|
||||
$reader = New-Object System.IO.StreamReader($errorResponse)
|
||||
$responseBody = $reader.ReadToEnd()
|
||||
Write-Error "Sectigo API Error Response: $responseBody"
|
||||
}
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
|
||||
|
||||
Function Get-SectigoApiToken {
|
||||
|
||||
#[CmdletBinding()]
|
||||
|
||||
. $PSScriptRoot\..\Private\Set-Onload.ps1
|
||||
[string]$tokenEndpoint = $AuthBaseAPIUrl + "/auth/realms/apiclients/protocol/openid-connect/token"
|
||||
|
||||
$clientId=$env:Sectigoclientid
|
||||
$clientSecret=$env:SectigoclientSecret
|
||||
|
||||
if (-Not $clientid) {
|
||||
$clientid=Read-Host "Please enter your clientid"
|
||||
}
|
||||
|
||||
if (-Not $clientSecret) {
|
||||
$clientSecret=Read-Host "Please enter your clientSecret"
|
||||
}
|
||||
|
||||
Write-Verbose -Verbose "tokenEndpoint: $tokenEndpoint "
|
||||
|
||||
# Prepare the body for the token request
|
||||
$body = @{
|
||||
grant_type = "client_credentials"
|
||||
client_id = $clientId
|
||||
client_secret = $clientSecret
|
||||
|
||||
}
|
||||
|
||||
. $PSScriptRoot\..\Private\Set-Onload.ps1
|
||||
|
||||
# Request the access token
|
||||
try {
|
||||
$tokenResponse = Invoke-RestMethod -Uri $tokenEndpoint -Method Post -Body $body -ContentType "application/x-www-form-urlencoded"
|
||||
$accessToken = $tokenResponse.access_token
|
||||
$env:SectigoToken=$accessToken
|
||||
if ($accesstoken) { Write-Verbose -Verbose 'Token Set $ENV:SectigoToken'}
|
||||
|
||||
}
|
||||
catch {
|
||||
Write-Error "Failed to obtain access token: $($_.Exception.Message)"
|
||||
#exit 1
|
||||
}
|
||||
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
|
||||
function Get-SectigoCertificate {
|
||||
[CmdletBinding(SupportsShouldProcess=$true)]
|
||||
param (
|
||||
[string]$ApiToken=$env:SectigoToken,
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$OrderId
|
||||
)
|
||||
|
||||
if (-Not $ApiToken) {
|
||||
$ApiToken=Read-Host "ApiToken:"
|
||||
}
|
||||
|
||||
. $PSScriptRoot\..\Private\Set-Onload.ps1
|
||||
|
||||
# [string]$dcvUrl = "${BaseAPIUrl}/api/ssl/v1/${OrderId}/dcv"
|
||||
[string]$dcvUrl = "${BaseAPIUrl}/api/ssl/v1/${OrderId}"
|
||||
|
||||
|
||||
$headers = @{
|
||||
"Authorization" = "Bearer $ApiToken"
|
||||
"Content-Type" = "application/json" # <-- Cleaned up syntax
|
||||
}
|
||||
|
||||
# --- API Call ---
|
||||
Write-Verbose "Attempting to retrieve certificate for Order ID: $OrderId"
|
||||
|
||||
try {
|
||||
$response = Invoke-RestMethod -Uri $dcvUrl -Method Get -Headers $headers -UseBasicParsing -ErrorAction Stop
|
||||
return $response
|
||||
} catch {
|
||||
Write-Error "API Request Failed: $($_.Exception.Message)"
|
||||
return $null
|
||||
}
|
||||
$response
|
||||
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
|
||||
|
||||
function Get-SectigoCertificateTypes {
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[string]$ApiToken=$env:SectigoToken
|
||||
)
|
||||
|
||||
if (-Not $ApiToken) {
|
||||
$ApiToken=Read-Host "ApiToken:"
|
||||
}
|
||||
|
||||
. $PSScriptRoot\..\Private\Set-Onload.ps1
|
||||
|
||||
[string]$CertificateTypesUrl= $BaseAPIUrl + "/api/ssl/v1/types"
|
||||
Write-Verbose -Verbose "CertificateTypesUrl: $CertificateTypesUrl"
|
||||
|
||||
# 1. Prepare the Authorization Header
|
||||
# The Sectigo API usually requires the token in a Bearer authorization header.
|
||||
$headers = @{
|
||||
"Authorization" = "Bearer $ApiToken"
|
||||
"Content-Type" = "application/json"
|
||||
}
|
||||
|
||||
# 2. Send the Request (GET is the standard method for listing resources)
|
||||
$response = Invoke-WebRequest -Uri $CertificateTypesUrl -Method Get -Headers $headers -UseBasicParsing
|
||||
|
||||
if ($response.StatusCode -eq 200) {
|
||||
# 3. Process the Response
|
||||
$certTypes = $response.Content | ConvertFrom-Json
|
||||
|
||||
# ASSUMPTION: The API returns an array of objects,
|
||||
# each representing a certificate type.
|
||||
# This function returns the entire list/array.
|
||||
return $certTypes
|
||||
|
||||
} else {
|
||||
Write-Error "Failed to get Certificate Types. Status code: $($response.StatusCode)."
|
||||
Write-Error "Response content: $($response.Content)"
|
||||
return $null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
# Load Configuration Variables
|
||||
|
||||
|
||||
function Get-SectigoOrg {
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[string]$ApiToken=$env:SectigoToken
|
||||
)
|
||||
|
||||
if (-Not $ApiToken) {
|
||||
$ApiToken=Read-Host
|
||||
}
|
||||
|
||||
. $PSScriptRoot\..\Private\Set-Onload.ps1
|
||||
[string]$OrganizationLookupUrl=$BaseAPIUrl + "/api/organization/v1"
|
||||
|
||||
# 1. Prepare the Authorization Header
|
||||
$headers = @{
|
||||
"Authorization" = "Bearer $ApiToken"
|
||||
"Content-Type" = "application/json"
|
||||
}
|
||||
|
||||
. $PSScriptRoot\..\Private\Set-Onload.ps1
|
||||
|
||||
try {
|
||||
# Invoke the web request to the Sectigo API
|
||||
$Response = Invoke-WebRequest -Uri $OrganizationLookupUrl -Headers $Headers -Method GET
|
||||
|
||||
# Check if the request was successful
|
||||
if ($Response.StatusCode -eq 200) {
|
||||
# Parse the JSON response
|
||||
$Organizations = $Response.Content | ConvertFrom-Json
|
||||
$Organizations|select-object id, name
|
||||
$Organizations.departments
|
||||
|
||||
} else {
|
||||
Write-Error "Failed to retrieve organizations. Status Code: $($Response.StatusCode)"
|
||||
Write-Error "Response Content: $($Response.Content)"
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Error "An error occurred during the API call: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
# Load Configuration Variables
|
||||
|
||||
|
||||
function Get-SectigoSeverTypes {
|
||||
[CmdletBinding()]
|
||||
param (
|
||||
[string]$ApiToken=$env:SectigoToken
|
||||
)
|
||||
|
||||
if (-Not $ApiToken) {
|
||||
$ApiToken=Read-Host
|
||||
}
|
||||
|
||||
. $PSScriptRoot\..\Private\Set-Onload.ps1
|
||||
[string]$OrganizationLookupUrl=$BaseAPIUrl + "/api/v1/servertype"
|
||||
|
||||
# 1. Prepare the Authorization Header
|
||||
$headers = @{
|
||||
"Authorization" = "Bearer $ApiToken"
|
||||
"Content-Type" = "application/json"
|
||||
}
|
||||
|
||||
. $PSScriptRoot\..\Private\Set-Onload.ps1
|
||||
|
||||
try {
|
||||
# Invoke the web request to the Sectigo API
|
||||
$Response = Invoke-WebRequest -Uri $OrganizationLookupUrl -Headers $Headers -Method GET
|
||||
|
||||
# Check if the request was successful
|
||||
if ($Response.StatusCode -eq 200) {
|
||||
# Parse the JSON response
|
||||
$Response.Content | ConvertFrom-Json
|
||||
|
||||
|
||||
} else {
|
||||
Write-Error "Failed to retrieve organizations. Status Code: $($Response.StatusCode)"
|
||||
Write-Error "Response Content: $($Response.Content)"
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Error "An error occurred during the API call: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
|
||||
function Revoke-SectigoCertificate {
|
||||
[CmdletBinding(SupportsShouldProcess=$true)]
|
||||
param (
|
||||
[string]$ApiToken=$env:SectigoToken,
|
||||
|
||||
[int]$reasonCode=4,
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$reason,
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$OrderId
|
||||
)
|
||||
|
||||
if (-Not $ApiToken) {
|
||||
$ApiToken=Read-Host
|
||||
}
|
||||
. $PSScriptRoot\..\Private\Set-Onload.ps1
|
||||
|
||||
[string]$RevokeUrl = "${BaseAPIUrl}/api/ssl/v1/revoke/${OrderId}"
|
||||
|
||||
Write-Verbose -Verbose "RequestUrl: $RevokeUrl"
|
||||
|
||||
$headers = @{
|
||||
"Authorization" = "Bearer $ApiToken"
|
||||
"Content-Type" = "application/json" # <-- Cleaned up syntax
|
||||
}
|
||||
|
||||
$body = @{
|
||||
reasonCode = $reasonCode
|
||||
reason = $reasonCode
|
||||
}
|
||||
|
||||
$jsonBody = $body | ConvertTo-Json
|
||||
|
||||
# --- API Call ---
|
||||
Write-Verbose "Attempting to retrieve certificate for Order ID: $OrderId"
|
||||
|
||||
try {
|
||||
$response=Invoke-RestMethod -Uri $RevokeUrl -Method POST -Headers $headers -Body $jsonBody -ContentType "application/json"
|
||||
return $response
|
||||
"Success"
|
||||
} catch {
|
||||
Write-Error "API Request Failed: $($_.Exception.Message)"
|
||||
return $null
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
|
||||
function Test-SectigoCertificateRequest {
|
||||
[CmdletBinding(SupportsShouldProcess=$true)]
|
||||
param (
|
||||
[string]$FilePath,
|
||||
[string]$csr
|
||||
)
|
||||
|
||||
if ($FilePath) {
|
||||
[string]$csr = (Get-Content -Path $FilePath -Raw)
|
||||
}
|
||||
|
||||
[string]$dcvUrl = "https://certificates.nd.gov/api/csr/validate/string"
|
||||
|
||||
|
||||
$headers = @{
|
||||
"accept" = "application/json"
|
||||
"Content-Type" = "application/json" # <-- Cleaned up syntax
|
||||
}
|
||||
|
||||
$Body = @{
|
||||
"csr" = $csr
|
||||
}
|
||||
|
||||
$jsonBody = $body | ConvertTo-Json
|
||||
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||
# --- API Call ---
|
||||
Write-Verbose "Attempting to retrieve certificate for Order ID: $OrderId"
|
||||
|
||||
try {
|
||||
$response = Invoke-RestMethod -Uri $dcvUrl -Method Post -Headers $headers -Body $jsonBody
|
||||
$response
|
||||
} catch {
|
||||
Write-Error "API Request Failed: $($_.Exception.Message)"|convertfrom-json
|
||||
return $null
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
# ITD.Infra-Certificate-Internal.Sectigo
|
||||
|
||||
### Written by: Freeman Peterson fjpeterson@nd.gov
|
||||
|
||||
# Description
|
||||
This module is used to interact Sectigo API
|
||||
|
||||
## Prerequisites
|
||||
None
|
||||
|
||||
# Api Documentation
|
||||
https://www.sectigo.com/knowledge-base/detail/Sectigo-Certificate-Manager-SCM-REST-API/kA01N000000XDkE
|
||||
|
||||
# Git repo
|
||||
https://dev.azure.com/ndgov/NDIT-WindowsServerTeam/_git/ITD.Infra-Certificate-Internal.Sectigo
|
||||
|
||||
# Install
|
||||
|
||||
### Add Gallary
|
||||
```
|
||||
Register-PSRepository -Name ITD_PwshGallery `
|
||||
-SourceLocation "https://powershell.nd.gov/ITD_PwshGallery/nuget/" `
|
||||
-PublishLocation "https://powershell.nd.gov/ITD_PwshGallery/nuget/" `
|
||||
-InstallationPolicy Trusted
|
||||
```
|
||||
|
||||
### Install Module
|
||||
```
|
||||
Find-Module -Repository ITD_PwshGallery -Name ITD.Infra-Certificate-Internal.Sectigo|Install-Module -Scope CurrentUser
|
||||
```
|
||||
|
||||
### Validate Module installed
|
||||
```
|
||||
Get-Command -Module ITD.Infra-Certificate-Internal.Sectigo
|
||||
```
|
||||
### Update Module
|
||||
```
|
||||
Find-Module -Repository ITD_PwshGallery -Name ITD.Infra-Certificate-Internal.Sectigo|Update-Module
|
||||
```
|
||||
|
||||
# Examples and Information
|
||||
|
||||
### Obtaining CSR From File
|
||||
```
|
||||
$csr = (Get-Content -Path "c:\temp\hostname.csr" -Raw)
|
||||
```
|
||||
|
||||
### Get Token Prompt for Creds
|
||||
```
|
||||
$env:Sectigoclientid='b16d95fd-405f-4d41-a748-c1035916a359'
|
||||
$env:SectigoclientSecret=redacted
|
||||
|
||||
Get-SectigoApiToken
|
||||
```
|
||||
|
||||
|
||||
### Test Cert Request
|
||||
```
|
||||
Test-SectigoCertificateRequest -FilePath $csrpath
|
||||
```
|
||||
|
||||
### Enroll the CSR
|
||||
```
|
||||
$certRequest = Enroll-SectigoCertificateRequest -Csr $csr -dcvEmail 'youremail@nd.gov" #-Comment "app123"
|
||||
```
|
||||
|
||||
### Get Cert Status
|
||||
```
|
||||
Get-SectigoCertificate -Orderid $certRequest.sslid
|
||||
```
|
||||
|
||||
### Wait for approval
|
||||
```
|
||||
while ($certstatus -ne "Issued") {
|
||||
$certstatus=(Get-SectigoCertificate -OrderId $certRequest.sslid).status
|
||||
Sleep 1
|
||||
}
|
||||
```
|
||||
|
||||
### Download Cert
|
||||
```
|
||||
$CertPath = (Download-SectigoCertificate -Orderid $certRequest.sslid -Format "pem").FullName
|
||||
```
|
||||
|
||||
Default Format: Pem
|
||||
'x509' - for Certificate (w/ chain) PEM encoded
|
||||
'x509CO' - for Certificate only, PEM encoded
|
||||
'base64' - for PKCS#7, PEM encoded
|
||||
'bin' - for PKCS#7, 'x509IO' - for Root/Intermediate(s) only, PEM encoded
|
||||
'x509IOR' - for Intermediate(s)/Root only, PEM encoded
|
||||
'pem' - for Certificate (w/ chain), PEM encoded
|
||||
'pemco' - for Certificate only, PEM encoded
|
||||
'pemia' - for Certificate (w/ issuer after), PEM encoded
|
||||
'x509R' - for Certificate (w/ chain), PEM encoded
|
||||
base64
|
||||
|
||||
### Add it to a cert store
|
||||
As administrator:
|
||||
```
|
||||
Import-Certificate -FilePath "C:\Certs\cert_OrderNumber.pem" -CertStoreLocation Cert:\LocalMachine\My
|
||||
```
|
||||
|
||||
# Other functions
|
||||
|
||||
### Revoke
|
||||
```
|
||||
Revoke-SectigoCertificate -reasonCode 4 -reason "Just a test" -Orderid 11012388
|
||||
```
|
||||
No results will be given back to you.
|
||||
|
||||
*If you revoke a cert you will no longer see them in Get-SectigoCertificate
|
||||
Reason code (unspecified (0), keyCompromise (1), affiliationChanged (3), superseded (4), cessationOfOperation (5))
|
||||
|
||||
### Org Lookup
|
||||
```
|
||||
Get-SectigoOrg
|
||||
```
|
||||
|
||||
### Certificate Types
|
||||
```
|
||||
Get-SectigoCertificateTypes
|
||||
```
|
||||
+41951
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user