Connect.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
159
160
161
162
163
164
165
function Get-Terraform {
    <#
    .SYNOPSIS
    Get Terraform server configuration.
 
    .DESCRIPTION
    Get the Server name, API Token and Org stored in your local config file.
    #>


    [CmdletBinding()]
    param()

    function Decrypt {
        param($String)
        
        if ($String -is [System.Security.SecureString]) {
            [System.Runtime.InteropServices.marshal]::PtrToStringAuto([System.Runtime.InteropServices.marshal]::SecureStringToBSTR($String))
        }
    }

    try {
        Import-Clixml -Path $Script:TerraformConfig | Select-Object -Property Server,@{n='Token';e={Decrypt $_.Token}},Org
    } catch {
        Write-Warning "Unable to import config file $($Script:TerraformConfig) : $($_.Exception.Message) : Line $($_.InvocationInfo.ScriptLineNumber)"
    }
}

function Set-Terraform {
    <#
    .SYNOPSIS
    Set Terraform server configuration.
 
    .DESCRIPTION
    Set the Server name, API Token and Org to store in your local config file.
 
    Multiple servers are supported. Use Connect-Terraform to switch servers.
 
        WARNING: Use this to store the token on a filesystem at your own risk
                 Only supported on Windows via Data Protection API
    #>


    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string]$Server,

        [Parameter(Mandatory)]
        [string]$Token,

        [Parameter(Mandatory)]
        [string]$Org
    )

    Switch ($PSBoundParameters.Keys) {
        'Server'    {$Script:Terraform.Server = $Server}
        'Token'     {$Script:Terraform.Token = $Token}
        'Org'       {$Script:Terraform.Org = $Org}
    }

    function Encrypt {
        param([string]$String)
        
        if ($String -notlike '' -and (Test-IsWindows)) {
            ConvertTo-SecureString -String $String -AsPlainText -Force
        } else {
            ConvertTo-SecureString -String $String -AsPlainText -Force
        }
    }

    $XML = @(Import-Clixml -Path $Script:TerraformConfig)

    if (!($XML.Server)) {
        #No file, create new file
        $Script:Terraform | Select-Object Server,@{n='Token';e={Encrypt $_.Token}},Org | Export-Clixml -Path $Script:TerraformConfig -force
    } elseif ($XML.Server -match "$Server") {
        #File exists, update existing server
        $XML | Where-Object Server -eq $Server | ForEach-Object {$_.Token=(Encrypt $Token)}
        $XML | Export-Clixml -Path $Script:TerraformConfig -force
    } else {
        #File exists, add new server
        $XML += $Script:Terraform | Select-Object Server,@{n='Token';e={Encrypt $_.Token}},Org
        $XML | Export-Clixml -Path $Script:TerraformConfig -force
    }
}

function Connect-Terraform {
    <#
    .SYNOPSIS
    Load autentication token into memory. Load via Terracreds (cross platform) or from encrypted config file (Windows).
 
    Terracreds is preferred and leverages the operating system vault: https://github.com/tonedefdev/terracreds
 
    .DESCRIPTION
    With Terracreds:
        Connect-Terraform app.terraform.io -Org <org>
 
    Without Terracreds (Windows Only):
        Use Get-Terraform and Set-Terraform to manage your server connections.
 
        WARNING: Use this to store the token on a filesystem at your own risk
                 Only supported on Windows via Data Protection API
     
    .EXAMPLE
    Connect-Terraform -Server app.terraform.io -Org MyOrg -Terracreds
     
    Using -Terracreds will retrieve your token from your local credential manager. -Org is required.
 
    .EXAMPLE
    Connect-Terraform -Server app.terraform.io
 
    Retrieve your token from your encrypted config file. Only supported by Windows.
    Note: The first server stored in your config file is automatically loaded when you import this module.
    #>


    [CmdletBinding()]
    param(
        [Parameter(Position=0,Mandatory)]
        [string]$Server,
        
        [Parameter(Mandatory,ParameterSetName='Terracreds')]
        [string]$Org,

        [Parameter(Mandatory,ParameterSetName='Terracreds')]
        [switch]$Terracreds
    )

    if ($Terracreds) {

        try {
            $Script:Terraform = [PSCustomObject]@{
                Server = $Server
                Token = (Invoke-Expression -Command "terracreds get $Server" | ConvertFrom-Json).token
                Org = $Org
            }
        } catch {
            Write-Warning "Terracreds error for $Server. Use 'terracreds --help' : $($_.Exception.Message) : Line $($_.InvocationInfo.ScriptLineNumber)"
            Continue
        }
        
    } else {

        $Script:Terraform = Get-Terraform | Where-Object Server -eq $Server

    }
}

$TerraformConfig = Get-TerraformConfig

# Create initial file until Set-Terraform is run
if (!(Test-Path -Path $Script:TerraformConfig -ea SilentlyContinue)) {
    try {

        [PSCustomObject]@{
            Server = $null
            Token = $null
            Org = $null
        } | Export-Clixml -Path $Script:TerraformConfig -force

    } catch {
        Write-Warning "Unable to create config file $($Script:TerraformConfig) : $($_.Exception.Message) : Line $($_.InvocationInfo.ScriptLineNumber)"
    }
}

$Terraform = (Get-Terraform)[0]