Public/Get-PAAuthorization.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
function Get-PAAuthorization {
    [CmdletBinding()]
    [OutputType('PoshACME.PAAuthorization')]
    param(
        [Parameter(Mandatory,Position=0,ValueFromPipeline,ValueFromPipelineByPropertyName)]
        [Alias('authorizations')]
        [string[]]$AuthURLs,
        [Parameter(Position=1)]
        [PSTypeName('PoshACME.PAAccount')]$Account
    )

    # Every order has an array of authorization URLs that can be used to
    # retrieve the current state of the authorization object which we want to
    # return to the caller. However, most of what a caller would care about is
    # the state of the associated challenges for that authorization.

    # To make processing easier, we're going to flatten the challenge data so you don't
    # have to loop into a sub-array. This may get unwieldy if too many additional
    # challenge types are added in the future.

    Begin {
        # make sure any account passed in is actually associated with the current server
        # or if no account was specified, that there's a current account.
        if (!$Account) {
            if (!($Account = Get-PAAccount)) {
                try { throw "No Account parameter specified and no current account selected. Try running Set-PAAccount first." }
                catch { $PSCmdlet.ThrowTerminatingError($_) }
            }
        } else {
            if ($Account.id -notin (Get-PAAccount -List).id) {
                try { throw "Specified account id $($Account.id) was not found in the current server's account list." }
                catch { $PSCmdlet.ThrowTerminatingError($_) }
            }
        }
        # make sure it's valid
        if ($Account.status -ne 'valid') {
            try { throw "Account status is $($Account.status)." }
            catch { $PSCmdlet.ThrowTerminatingError($_) }
        }
    }

    Process {
        foreach ($AuthUrl in $AuthUrls) {

            # request the object
            try {
                $header = @{alg=$Account.alg; kid=$Account.location;nonce=$script:Dir.nonce;url=$AuthUrl}
                $response = Invoke-ACME $header ([String]::Empty) $Account -EA Stop
                $auth = $response.Content | ConvertFrom-Json
            } catch [AcmeException] {
                if ($_.Exception.Data.status -eq 404) {
                    Write-Warning "Authorization not found on server. $($_.Exception.Data.detail)"
                    continue
                } else { throw }
            }
            # inject the type name
            $auth.PSObject.TypeNames.Insert(0,'PoshACME.PAAuthorization')

            # Workaround non-compliant ACME servers such as Nexus CM that don't include
            # the status field on challenge objects. Just copy the auth's status to
            # each challenge.
            $nonCompliantServer = $false
            $auth.challenges | ForEach-Object {
                if ('status' -notin $_.PSObject.Properties.Name) {
                    $nonCompliantServer = $true
                    $_ | Add-Member -MemberType NoteProperty -Name 'status' -Value $auth.status
                }
            }
            if ($nonCompliantServer) {
                Write-Warning "ACME server returned non-compliant challenge objects with no status. Please report this to your ACME server vendor."
            }

            # According to RFC 8555 7.1.4 the expires property is only REQUIRED when the property status is "valid".
            # It's OPTIONAL for any other status and some CA's will not return it.
            # Only repair the timestamp if it actually exists
            if ('expires' -in $auth.PSObject.Properties.Name) {
                # fix any dates that may have been parsed by PSCore's JSON serializer
                $auth.expires = Repair-ISODate $auth.expires
            }

            # add "nice to have" members to the auth object
            # add members that expose the details of the 'dns-01' and 'http-01'
            # challenge in the root of the object
            $auth | Add-Member -NotePropertyMembers @{
                DNSId        = $auth.identifier.value
                fqdn         = "$(if ($auth.wildcard) {'*.'})$($auth.identifier.value)"
                location     = $AuthUrl
                DNS01Status  = $null
                DNS01Url     = $null
                DNS01Token   = $null
                HTTP01Status = $null
                HTTP01Url    = $null
                HTTP01Token  = $null
            }

            $dnsChallenge = $auth.challenges | Where-Object { $_.type -eq 'dns-01' }
            if ($dnsChallenge) {
                $auth.DNS01Status = $dnsChallenge.status
                $auth.DNS01Url    = $dnsChallenge.url
                $auth.DNS01Token  = $dnsChallenge.token
            }

            $httpChallenge = $auth.challenges | Where-Object { $_.type -eq 'http-01' }
            if ($httpChallenge) {
                $auth.HTTP01Status = $httpChallenge.status
                $auth.HTTP01Url    = $httpChallenge.url
                $auth.HTTP01Token  = $httpChallenge.token
            }

            Write-Output $auth

        }
    }





    <#
    .SYNOPSIS
        Get the authorizations associated with a particular order or set of authorization URLs.
 
    .DESCRIPTION
        Returns details such as fqdn, status, expiration, and challenges for one or more ACME authorizations.
 
    .PARAMETER AuthURLs
        One or more authorization URLs. You also pipe in one or more PoshACME.PAOrder objects.
 
    .PARAMETER Account
        An existing ACME account object such as the output from Get-PAAccount. If no account is specified, the current account will be used.
 
    .EXAMPLE
        Get-PAAuthorization https://acme.example.com/authz/1234567
 
        Get the authorization for the specified URL.
 
    .EXAMPLE
        Get-PAOrder | Get-PAAuthorization
 
        Get the authorizations for the current order on the current account.
 
    .EXAMPLE
        Get-PAOrder -List | Get-PAAuthorization
 
        Get the authorizations for all orders on the current account.
 
    .LINK
        Project: https://github.com/rmbolger/Posh-ACME
 
    .LINK
        Get-PAOrder
 
    .LINK
        New-PAOrder
 
    #>

}