-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 1a425cd
Showing
4 changed files
with
316 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2024 Joe Garcia | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
# psConjur | ||
|
||
   | ||
|
||
`psConjur` is a PowerShell module for authenticating to and retrieving secrets from Conjur’s REST API. It supports session-based authentication to streamline repeated requests. | ||
|
||
## Installation | ||
|
||
### From PowerShell Gallery | ||
|
||
You can install `psConjur` directly from the PowerShell Gallery: | ||
|
||
```powershell | ||
Install-Module -Name psConjur -Scope CurrentUser | ||
``` | ||
|
||
### Manual Installation | ||
|
||
Download the module files and import them into your PowerShell session: | ||
|
||
```powershell | ||
Import-Module .\psConjur\psConjur.psd1 | ||
``` | ||
|
||
## Usage | ||
|
||
### Initialize a Conjur Session | ||
|
||
Initialize a session with Conjur to set up common parameters (`ApplianceUrl`, `Account`, and `AuthToken`) for reuse across multiple commands: | ||
|
||
```powershell | ||
Initialize-ConjurSession -ApplianceUrl "https://your-conjur-appliance.com/api" -Account "conjur" -AuthToken "your-auth-token" -ExpiryMinutes 30 | ||
``` | ||
|
||
* `ExpiryMinutes` is optional and defaults to 30 minutes. | ||
|
||
### Authentication | ||
|
||
Use the `Get-ConjurAuthToken` function to authenticate and obtain an access token. This supports both JWT and API Key authentication methods. | ||
|
||
#### JWT Authentication | ||
|
||
```powershell | ||
$authToken = Get-ConjurAuthToken -ServiceID "your-service-id" -JWTToken "your-jwt-token" | ||
``` | ||
|
||
#### Username + API Key Authentication | ||
|
||
```powershell | ||
$authToken = Get-ConjurAuthToken -Username "your-username" -ApiKey "your-api-key" | ||
``` | ||
|
||
The retrieved `AuthToken` will automatically update the session and reset the expiration time. | ||
|
||
### Retrieve a Secret | ||
|
||
Retrieve a single secret using the `Get-ConjurSecret` function: | ||
|
||
```powershell | ||
$secret = Get-ConjurSecret -SecretId "my/secret/id" | ||
``` | ||
|
||
### Retrieve Multiple Secrets in Bulk | ||
|
||
Retrieve multiple secrets at once by providing an array of secret IDs to `Get-ConjurSecretsBulk`: | ||
|
||
```powershell | ||
$secrets = Get-ConjurSecretsBulk -SecretIds @("secret/id/one", "secret/id/two") | ||
``` | ||
|
||
### Clear the Conjur Session | ||
|
||
When finished, manually clear the session data to remove sensitive information from memory: | ||
|
||
```powershell | ||
Clear-ConjurSession | ||
``` | ||
|
||
## Security | ||
|
||
### Security Implications and Recommendations | ||
|
||
Using a session-based approach for storing authentication and connection information introduces security implications. Here are key considerations and recommendations: | ||
|
||
1. **Session Persistence**: Sensitive data, including the `AuthToken`, remains in memory during the session. This provides convenience but poses a risk if the PowerShell session remains open and unattended. | ||
- **Recommendation**: Always clear the session manually with `Clear-ConjurSession` when done, and avoid using this module in long-running, unattended sessions. | ||
2. **Session Expiration**: Sessions expire after a set time (default is 30 minutes) to prevent indefinite access with stale tokens. | ||
- **Recommendation**: Set an appropriate expiration time based on your security needs using `ExpiryMinutes` in `Initialize-ConjurSession`. | ||
3. **Unauthorized Access**: If another user gains access to the PowerShell session, they could potentially access stored tokens. | ||
- **Recommendation**: Limit access to the system, and use PowerShell’s ConstrainedLanguage mode to restrict unauthorized users in shared environments. | ||
4. **Memory Exposure**: Sensitive session data stored in memory could be accessed if the host is compromised. | ||
- **Recommendation**: Secure the host machine and consider automatic session clearing or periodic re-authentication in high-security environments. | ||
5. **Audit Logging**: This module does not log actions by default, which may complicate auditing. | ||
- **Recommendation**: Enable custom logging for critical actions as needed, depending on your organization’s audit requirements. | ||
|
||
By following these best practices, you can securely leverage the session-based functionality in `psConjur` for efficient Conjur API access. | ||
|
||
## Contributing | ||
|
||
Feel free to submit issues and pull requests. Please ensure code is formatted for readability and follows PowerShell best practices. | ||
|
||
## License | ||
|
||
[MIT](LICENSE) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
@{ | ||
# Module metadata | ||
ModuleVersion = '1.0.0' | ||
GUID = 'put-a-unique-guid-here' | ||
Author = 'Your Name' | ||
CompanyName = 'Your Company' | ||
Description = 'A PowerShell module for interacting with Conjur REST API for authentication and secret management.' | ||
Copyright = '(c) Your Name. All rights reserved.' | ||
|
||
# Functions to export | ||
FunctionsToExport = @( | ||
'Get-ConjurAuthToken', | ||
'Get-ConjurSecret' | ||
) | ||
|
||
# Required modules (if any) | ||
RequiredModules = @() | ||
|
||
# PowerShell version compatibility | ||
PowerShellVersion = '5.1' | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
# psConjur.psm1 - PowerShell Module for Conjur REST API | ||
# Author: Joe Garcia ([email protected]) | ||
# Description: A PowerShell module to authenticate with and retrieve secrets from Conjur REST API. | ||
|
||
# Module-scoped session data | ||
$script:ConjurSession = @{ | ||
ApplianceUrl = $null | ||
Account = $null | ||
AuthToken = $null | ||
ExpiryTime = $null | ||
} | ||
|
||
# Function to initialize a Conjur session with automatic expiry | ||
function Initialize-ConjurSession { | ||
<# | ||
.SYNOPSIS | ||
Initializes a session with common Conjur parameters. | ||
.PARAMETER ApplianceUrl | ||
The base URL of the Conjur appliance. | ||
.PARAMETER Account | ||
The Conjur account name. | ||
.PARAMETER AuthToken | ||
The access token obtained from Get-ConjurAuthToken. | ||
.PARAMETER ExpiryMinutes | ||
Optional. Number of minutes until the session expires and needs re-authentication. | ||
.EXAMPLE | ||
Initialize-ConjurSession -ApplianceUrl "https://your-conjur-appliance.com/api" -Account "conjur" -AuthToken $authToken -ExpiryMinutes 30 | ||
#> | ||
|
||
param ( | ||
[string]$ApplianceUrl, | ||
[string]$Account, | ||
[string]$AuthToken, | ||
[int]$ExpiryMinutes = 30 | ||
) | ||
|
||
# Store session parameters with expiry time | ||
$script:ConjurSession['ApplianceUrl'] = $ApplianceUrl | ||
$script:ConjurSession['Account'] = $Account | ||
$script:ConjurSession['AuthToken'] = $AuthToken | ||
$script:ConjurSession['ExpiryTime'] = (Get-Date).AddMinutes($ExpiryMinutes) | ||
} | ||
|
||
# Function to clear the Conjur session data | ||
function Clear-ConjurSession { | ||
<# | ||
.SYNOPSIS | ||
Clears the current Conjur session data, including any stored authentication tokens. | ||
#> | ||
|
||
$script:ConjurSession = @{ | ||
ApplianceUrl = $null | ||
Account = $null | ||
AuthToken = $null | ||
ExpiryTime = $null | ||
} | ||
} | ||
|
||
# Helper function to check session expiration and re-authenticate if expired | ||
function Test-ConjurSession { | ||
if (-not $script:ConjurSession['AuthToken'] -or (Get-Date) -gt $script:ConjurSession['ExpiryTime']) { | ||
throw "Session expired or not initialized. Please re-authenticate using Initialize-ConjurSession." | ||
} | ||
} | ||
|
||
# Updated Get-ConjurAuthToken function (unchanged but now relies on session) | ||
function Get-ConjurAuthToken { | ||
param ( | ||
[string]$ServiceID, | ||
[string]$JWTToken, | ||
[string]$Username, | ||
[string]$ApiKey | ||
) | ||
|
||
$ApplianceUrl = $script:ConjurSession['ApplianceUrl'] | ||
$Account = $script:ConjurSession['Account'] | ||
|
||
if (!$ApplianceUrl -or !$Account) { | ||
throw "Please initialize the Conjur session with ApplianceUrl and Account using Initialize-ConjurSession." | ||
} | ||
|
||
try { | ||
if ($ServiceID -and $JWTToken) { | ||
$AuthHeader = "Token token=`"$JWTToken`"" | ||
$uri = "$ApplianceUrl/authn-jwt/$ServiceID/$Account/authenticate" | ||
$headers = @{ | ||
"Authorization" = $AuthHeader | ||
} | ||
$response = Invoke-RestMethod -Uri $uri -Headers $headers -Method Post | ||
} elseif ($Username -and $ApiKey) { | ||
$uri = "$ApplianceUrl/authn/$Account/$Username/authenticate" | ||
$response = Invoke-RestMethod -Uri $uri -Body $ApiKey -Method Post -ContentType "text/plain" | ||
} else { | ||
throw "Provide either ServiceID and JWTToken for JWT authentication or Username and ApiKey for username+apikey authentication." | ||
} | ||
|
||
# Update the session's AuthToken and reset expiry | ||
$script:ConjurSession['AuthToken'] = $response | ||
$script:ConjurSession['ExpiryTime'] = (Get-Date).AddMinutes(30) # Reset expiry to default 30 minutes | ||
return $response | ||
} catch { | ||
throw "Authentication failed: $_" | ||
} | ||
} | ||
|
||
# Updated function to retrieve a single secret, using session values and session check | ||
function Get-ConjurSecret { | ||
param ( | ||
[string]$SecretId | ||
) | ||
|
||
Test-ConjurSession | ||
$ApplianceUrl = $script:ConjurSession['ApplianceUrl'] | ||
$Account = $script:ConjurSession['Account'] | ||
$AuthToken = $script:ConjurSession['AuthToken'] | ||
|
||
$AuthHeader = "Token token=`"$AuthToken`"" | ||
$uri = "$ApplianceUrl/secrets/$Account/variable/$SecretId" | ||
$headers = @{ | ||
"Authorization" = $AuthHeader | ||
} | ||
|
||
try { | ||
$response = Invoke-RestMethod -Uri $uri -Headers $headers -Method Get | ||
return $response | ||
} catch { | ||
throw "Failed to retrieve secret: $_" | ||
} | ||
} | ||
|
||
# Updated function to retrieve multiple secrets in bulk, using session values and session check | ||
function Get-ConjurSecretsBulk { | ||
param ( | ||
[string[]]$SecretIds | ||
) | ||
|
||
Test-ConjurSession | ||
$ApplianceUrl = $script:ConjurSession['ApplianceUrl'] | ||
$Account = $script:ConjurSession['Account'] | ||
$AuthToken = $script:ConjurSession['AuthToken'] | ||
|
||
$AuthHeader = "Token token=`"$AuthToken`"" | ||
$headers = @{ | ||
"Authorization" = $AuthHeader | ||
} | ||
|
||
$secrets = @{} | ||
|
||
foreach ($secretId in $SecretIds) { | ||
$uri = "$ApplianceUrl/secrets/$Account/variable/$secretId" | ||
|
||
try { | ||
$secretValue = Invoke-RestMethod -Uri $uri -Headers $headers -Method Get | ||
$secrets[$secretId] = $secretValue | ||
} catch { | ||
Write-Warning "Failed to retrieve secret with ID ${secretId}: $_" | ||
$secrets[$secretId] = $null | ||
} | ||
} | ||
|
||
return $secrets | ||
} | ||
|
||
# Export functions | ||
Export-ModuleMember -Function Initialize-ConjurSession, Clear-ConjurSession, Get-ConjurAuthToken, Get-ConjurSecret, Get-ConjurSecretsBulk |