mirror of
https://github.com/bartvdbraak/keyweave.git
synced 2025-04-29 07:41:21 +00:00
Compare commits
No commits in common. "main" and "v0.2.4" have entirely different histories.
12 changed files with 615 additions and 903 deletions
9
.github/renovate.json
vendored
9
.github/renovate.json
vendored
|
@ -1,12 +1,5 @@
|
||||||
{
|
{
|
||||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||||
"extends": ["config:base"],
|
"extends": ["config:base"],
|
||||||
"reviewers": ["bartvdbraak"],
|
"reviewers": ["bartvdbraak"]
|
||||||
"packageRules": [
|
|
||||||
{
|
|
||||||
"matchPackagePrefixes": ["azure"],
|
|
||||||
"groupName": "Azure Dependencies",
|
|
||||||
"groupSlug": "azure-dependencies"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
45
.github/workflows/release.yml
vendored
45
.github/workflows/release.yml
vendored
|
@ -70,7 +70,7 @@ jobs:
|
||||||
experimental: false
|
experimental: false
|
||||||
|
|
||||||
- name: mac-arm64
|
- name: mac-arm64
|
||||||
os: macos-latest
|
os: macos-11.0
|
||||||
target: aarch64-apple-darwin
|
target: aarch64-apple-darwin
|
||||||
cross: true
|
cross: true
|
||||||
experimental: true
|
experimental: true
|
||||||
|
@ -87,12 +87,12 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/cache@v4
|
- uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: ~/.cargo/registry
|
path: ~/.cargo/registry
|
||||||
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('Cargo.lock') }}
|
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('Cargo.lock') }}
|
||||||
|
|
||||||
- uses: actions/cache@v4
|
- uses: actions/cache@v3
|
||||||
if: startsWith(matrix.name, 'linux-')
|
if: startsWith(matrix.name, 'linux-')
|
||||||
with:
|
with:
|
||||||
path: ~/.cargo/bin
|
path: ~/.cargo/bin
|
||||||
|
@ -104,6 +104,7 @@ jobs:
|
||||||
|
|
||||||
- uses: taiki-e/setup-cross-toolchain-action@v1
|
- uses: taiki-e/setup-cross-toolchain-action@v1
|
||||||
with:
|
with:
|
||||||
|
# NB: sets CARGO_BUILD_TARGET evar - do not need --target flag in build
|
||||||
target: ${{ matrix.target }}
|
target: ${{ matrix.target }}
|
||||||
|
|
||||||
- uses: taiki-e/install-action@cross
|
- uses: taiki-e/install-action@cross
|
||||||
|
@ -116,7 +117,7 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
echo "${{ needs.pre-check.outputs.version }}" > VERSION
|
echo "${{ needs.pre-check.outputs.version }}" > VERSION
|
||||||
|
|
||||||
- name: Archive and Package
|
- name: Package
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
set -euxo pipefail
|
set -euxo pipefail
|
||||||
|
@ -125,19 +126,24 @@ jobs:
|
||||||
bin="target/${{ matrix.target }}/release/keyweave${ext}"
|
bin="target/${{ matrix.target }}/release/keyweave${ext}"
|
||||||
strip "$bin" || true
|
strip "$bin" || true
|
||||||
dst="keyweave-${{ matrix.target }}"
|
dst="keyweave-${{ matrix.target }}"
|
||||||
mkdir -p "$dst" dist
|
mkdir "$dst"
|
||||||
cp "$bin" "$dst/"
|
cp "$bin" "$dst/"
|
||||||
if [[ "${{ matrix.name }}" == windows-* ]] ; then
|
|
||||||
mv "$dst/keyweave${ext}" dist/keyweave-${{ matrix.target }}.exe
|
|
||||||
else
|
|
||||||
tar cavf "$dst.tar.xz" "$dst"
|
|
||||||
mv "$dst.tar.xz" dist/
|
|
||||||
fi
|
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
- name: Archive (tar)
|
||||||
|
if: '! startsWith(matrix.name, ''windows-'')'
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euxo pipefail
|
||||||
|
dst="keyweave-${{ matrix.target }}"
|
||||||
|
tar cavf "$dst.tar.xz" "$dst"
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: dist-${{ matrix.target }}
|
name: builds
|
||||||
path: dist
|
retention-days: 1
|
||||||
|
path: |
|
||||||
|
keyweave-*.tar.xz
|
||||||
|
keyweave-x86_64-pc-windows-gnu/keyweave.exe
|
||||||
|
|
||||||
release:
|
release:
|
||||||
needs: build
|
needs: build
|
||||||
|
@ -152,22 +158,21 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/cache@v4
|
- uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: ~/.cargo/bin
|
path: ~/.cargo/bin
|
||||||
key: sign-tools-${{ hashFiles('.github/workflows/release.yml') }}
|
key: sign-tools-${{ hashFiles('.github/workflows/release.yml') }}
|
||||||
|
|
||||||
- uses: actions/download-artifact@v4
|
- uses: actions/download-artifact@v3
|
||||||
with:
|
with:
|
||||||
pattern: dist-*
|
name: builds
|
||||||
merge-multiple: true
|
|
||||||
|
|
||||||
- name: Checksums with SHA512 and SHA256
|
- name: Checksums with SHA512 and SHA256
|
||||||
run: |
|
run: |
|
||||||
sha512sum keyweave-* | tee SHA512SUMS
|
sha512sum keyweave-* | tee SHA512SUMS
|
||||||
sha256sum keyweave-* | tee SHA256SUMS
|
sha256sum keyweave-* | tee SHA256SUMS
|
||||||
|
|
||||||
- uses: softprops/action-gh-release@v2
|
- uses: softprops/action-gh-release@v1
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
|
@ -175,7 +180,7 @@ jobs:
|
||||||
fail_on_unmatched_files: true
|
fail_on_unmatched_files: true
|
||||||
files: |
|
files: |
|
||||||
keyweave-*.tar.xz
|
keyweave-*.tar.xz
|
||||||
keyweave-*.exe
|
keyweave-*/keyweave.exe
|
||||||
*SUMS*
|
*SUMS*
|
||||||
|
|
||||||
- name: Generate SHA256SUM input for Homebrew
|
- name: Generate SHA256SUM input for Homebrew
|
||||||
|
|
9
.github/workflows/tests.yml
vendored
9
.github/workflows/tests.yml
vendored
|
@ -54,14 +54,13 @@ jobs:
|
||||||
DEPLOYMENT_NAME: keyweave-${{ github.run_id }}
|
DEPLOYMENT_NAME: keyweave-${{ github.run_id }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: azure/login@v2
|
- uses: azure/login@v1
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets.AZURE_CLIENT_ID_BICEP }}
|
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
||||||
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
||||||
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
|
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
|
||||||
|
|
||||||
- name: Deploy Bicep template
|
- name: Deploy Bicep template
|
||||||
uses: azure/arm-deploy@v2
|
uses: azure/arm-deploy@v1
|
||||||
with:
|
with:
|
||||||
scope: subscription
|
scope: subscription
|
||||||
region: ${{ env.LOCATION }}
|
region: ${{ env.LOCATION }}
|
||||||
|
@ -95,7 +94,7 @@ jobs:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
- name: Azure Login
|
- name: Azure Login
|
||||||
uses: azure/login@v2
|
uses: azure/login@v1
|
||||||
with:
|
with:
|
||||||
client-id: ${{ secrets[matrix.client-id-ref] }}
|
client-id: ${{ secrets[matrix.client-id-ref] }}
|
||||||
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
||||||
|
|
|
@ -1,128 +0,0 @@
|
||||||
# Contributor Covenant Code of Conduct
|
|
||||||
|
|
||||||
## Our Pledge
|
|
||||||
|
|
||||||
We as members, contributors, and leaders pledge to make participation in our
|
|
||||||
community a harassment-free experience for everyone, regardless of age, body
|
|
||||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
|
||||||
identity and expression, level of experience, education, socio-economic status,
|
|
||||||
nationality, personal appearance, race, religion, or sexual identity
|
|
||||||
and orientation.
|
|
||||||
|
|
||||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
|
||||||
diverse, inclusive, and healthy community.
|
|
||||||
|
|
||||||
## Our Standards
|
|
||||||
|
|
||||||
Examples of behavior that contributes to a positive environment for our
|
|
||||||
community include:
|
|
||||||
|
|
||||||
* Demonstrating empathy and kindness toward other people
|
|
||||||
* Being respectful of differing opinions, viewpoints, and experiences
|
|
||||||
* Giving and gracefully accepting constructive feedback
|
|
||||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
|
||||||
and learning from the experience
|
|
||||||
* Focusing on what is best not just for us as individuals, but for the
|
|
||||||
overall community
|
|
||||||
|
|
||||||
Examples of unacceptable behavior include:
|
|
||||||
|
|
||||||
* The use of sexualized language or imagery, and sexual attention or
|
|
||||||
advances of any kind
|
|
||||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
|
||||||
* Public or private harassment
|
|
||||||
* Publishing others' private information, such as a physical or email
|
|
||||||
address, without their explicit permission
|
|
||||||
* Other conduct which could reasonably be considered inappropriate in a
|
|
||||||
professional setting
|
|
||||||
|
|
||||||
## Enforcement Responsibilities
|
|
||||||
|
|
||||||
Community leaders are responsible for clarifying and enforcing our standards of
|
|
||||||
acceptable behavior and will take appropriate and fair corrective action in
|
|
||||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
|
||||||
or harmful.
|
|
||||||
|
|
||||||
Community leaders have the right and responsibility to remove, edit, or reject
|
|
||||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
|
||||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
|
||||||
decisions when appropriate.
|
|
||||||
|
|
||||||
## Scope
|
|
||||||
|
|
||||||
This Code of Conduct applies within all community spaces, and also applies when
|
|
||||||
an individual is officially representing the community in public spaces.
|
|
||||||
Examples of representing our community include using an official e-mail address,
|
|
||||||
posting via an official social media account, or acting as an appointed
|
|
||||||
representative at an online or offline event.
|
|
||||||
|
|
||||||
## Enforcement
|
|
||||||
|
|
||||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
||||||
reported to the community leaders responsible for enforcement at
|
|
||||||
[bart@vanderbraak.nl](mailto:bart@vanderbraak.nl).
|
|
||||||
All complaints will be reviewed and investigated promptly and fairly.
|
|
||||||
|
|
||||||
All community leaders are obligated to respect the privacy and security of the
|
|
||||||
reporter of any incident.
|
|
||||||
|
|
||||||
## Enforcement Guidelines
|
|
||||||
|
|
||||||
Community leaders will follow these Community Impact Guidelines in determining
|
|
||||||
the consequences for any action they deem in violation of this Code of Conduct:
|
|
||||||
|
|
||||||
### 1. Correction
|
|
||||||
|
|
||||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
|
||||||
unprofessional or unwelcome in the community.
|
|
||||||
|
|
||||||
**Consequence**: A private, written warning from community leaders, providing
|
|
||||||
clarity around the nature of the violation and an explanation of why the
|
|
||||||
behavior was inappropriate. A public apology may be requested.
|
|
||||||
|
|
||||||
### 2. Warning
|
|
||||||
|
|
||||||
**Community Impact**: A violation through a single incident or series
|
|
||||||
of actions.
|
|
||||||
|
|
||||||
**Consequence**: A warning with consequences for continued behavior. No
|
|
||||||
interaction with the people involved, including unsolicited interaction with
|
|
||||||
those enforcing the Code of Conduct, for a specified period of time. This
|
|
||||||
includes avoiding interactions in community spaces as well as external channels
|
|
||||||
like social media. Violating these terms may lead to a temporary or
|
|
||||||
permanent ban.
|
|
||||||
|
|
||||||
### 3. Temporary Ban
|
|
||||||
|
|
||||||
**Community Impact**: A serious violation of community standards, including
|
|
||||||
sustained inappropriate behavior.
|
|
||||||
|
|
||||||
**Consequence**: A temporary ban from any sort of interaction or public
|
|
||||||
communication with the community for a specified period of time. No public or
|
|
||||||
private interaction with the people involved, including unsolicited interaction
|
|
||||||
with those enforcing the Code of Conduct, is allowed during this period.
|
|
||||||
Violating these terms may lead to a permanent ban.
|
|
||||||
|
|
||||||
### 4. Permanent Ban
|
|
||||||
|
|
||||||
**Community Impact**: Demonstrating a pattern of violation of community
|
|
||||||
standards, including sustained inappropriate behavior, harassment of an
|
|
||||||
individual, or aggression toward or disparagement of classes of individuals.
|
|
||||||
|
|
||||||
**Consequence**: A permanent ban from any sort of public interaction within
|
|
||||||
the community.
|
|
||||||
|
|
||||||
## Attribution
|
|
||||||
|
|
||||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
|
||||||
version 2.0, available at
|
|
||||||
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
|
||||||
|
|
||||||
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
|
||||||
enforcement ladder](https://github.com/mozilla/diversity).
|
|
||||||
|
|
||||||
[homepage]: https://www.contributor-covenant.org
|
|
||||||
|
|
||||||
For answers to common questions about this code of conduct, see the FAQ at
|
|
||||||
https://www.contributor-covenant.org/faq. Translations are available at
|
|
||||||
https://www.contributor-covenant.org/translations.
|
|
1171
Cargo.lock
generated
1171
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
24
Cargo.toml
24
Cargo.toml
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "keyweave"
|
name = "keyweave"
|
||||||
version = "0.3.1"
|
version = "0.2.4"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = ["Bart van der Braak <bart@vanderbraak.nl>"]
|
authors = ["Bart van der Braak <bart@vanderbraak.nl>"]
|
||||||
keywords = ["azure", "keyvault", "env"]
|
keywords = ["azure", "keyvault", "env"]
|
||||||
|
@ -10,20 +10,20 @@ documentation = "https://docs.rs/keyweave"
|
||||||
repository = "https://github.com/bartvdbraak/keyweave/"
|
repository = "https://github.com/bartvdbraak/keyweave/"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.82"
|
anyhow = "1.0.75"
|
||||||
azure_core = "0.21.0"
|
azure_core = "0.17.0"
|
||||||
azure_identity = "0.21.0"
|
azure_identity = "0.17.0"
|
||||||
azure_security_keyvault = "0.21.0"
|
azure_security_keyvault = "0.17.0"
|
||||||
clap = { version = "4.5.4", features = ["derive"] }
|
clap = { version = "4.4.10", features = ["derive"] }
|
||||||
futures = "0.3.30"
|
futures = "0.3.29"
|
||||||
paris = { version = "1.5.15", features = ["macros"] }
|
paris = { version = "1.5.15", features = ["macros"] }
|
||||||
tokio = {version = "1.37.0", features = ["full"]}
|
tokio = {version = "1.34.0", features = ["full"]}
|
||||||
|
|
||||||
[target.'cfg(all(target_os = "linux", any(target_env = "musl", target_arch = "arm", target_arch = "aarch64")))'.dependencies]
|
[target.'cfg(all(target_os = "linux", any(target_env = "musl", target_arch = "arm", target_arch = "aarch64")))'.dependencies]
|
||||||
openssl = { version = "0.10", features = ["vendored"] }
|
openssl = { version = "0.10", features = ["vendored"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
assert_cmd = "2.0.14"
|
assert_cmd = "2.0.12"
|
||||||
assert_fs = "1.1.1"
|
assert_fs = "1.0.13"
|
||||||
predicates = "3.1.0"
|
predicates = "3.0.4"
|
||||||
serial_test = "3.1.0"
|
serial_test = "2.0.0"
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
[<img alt="github" src="https://img.shields.io/badge/github-bartvdbraak/keyweave-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/bartvdbraak/keyweave)
|
[<img alt="github" src="https://img.shields.io/badge/github-bartvdbraak/keyweave-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/bartvdbraak/keyweave)
|
||||||
[<img alt="crates.io" src="https://img.shields.io/crates/v/keyweave.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/keyweave)
|
[<img alt="crates.io" src="https://img.shields.io/crates/v/keyweave.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/keyweave)
|
||||||
[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-keyweave-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/keyweave)
|
[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-keyweave-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/keyweave)
|
||||||
[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/bartvdbraak/keyweave/checks.yml?style=for-the-badge&branch=main" height="20">](https://github.com/bartvdbraak/keyweave/actions/workflows/checks.yml)
|
[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/bartvdbraak/keyweave/checks.yml?style=for-the-badge" height="20">](https://github.com/bartvdbraak/keyweave/actions/workflows/checks.yml)
|
||||||
[<img alt="test status" src="https://img.shields.io/github/actions/workflow/status/bartvdbraak/keyweave/tests.yml?style=for-the-badge&label=tests&branch=main" height="20">](https://github.com/bartvdbraak/keyweave/actions/workflows/tests.yml)
|
|
||||||
|
|
||||||
<img align="right" src="https://github.com/bartvdbraak/keyweave/assets/3996360/5461f53a-5cef-4bde-908a-b8d3bc1c71c5" alt="Keyweave" width="30%">
|
<img align="right" src="https://github.com/bartvdbraak/keyweave/assets/3996360/5461f53a-5cef-4bde-908a-b8d3bc1c71c5" alt="Keyweave" width="30%">
|
||||||
|
|
||||||
|
|
31
SECURITY.md
31
SECURITY.md
|
@ -1,31 +0,0 @@
|
||||||
# Security Policy
|
|
||||||
|
|
||||||
## Supported Versions
|
|
||||||
|
|
||||||
Use the latest version of Keyweave for the latest security updates.
|
|
||||||
|
|
||||||
## Reporting Vulnerabilities
|
|
||||||
|
|
||||||
To report a security issue, please email [bart@vanderbraak.nl](mailto:bart@vanderbraak.nl) with a detailed description and steps to reproduce. Do not file a public issue for security vulnerabilities.
|
|
||||||
|
|
||||||
### Response Timeline
|
|
||||||
|
|
||||||
We aim to respond to security reports within 48 hours, and to patch the issue within a reasonable timeframe depending on the severity.
|
|
||||||
|
|
||||||
### Responsible Disclosure
|
|
||||||
|
|
||||||
Please allow us a reasonable timeframe to address the issue before publicly disclosing it.
|
|
||||||
|
|
||||||
### Acknowledgements
|
|
||||||
|
|
||||||
We appreciate the responsible disclosure of issues by our users and will acknowledge contributors in our release notes.
|
|
||||||
|
|
||||||
## Security Best Practices
|
|
||||||
|
|
||||||
- Ensure you are running the latest version of Keyweave.
|
|
||||||
- Follow secure password and authentication practices.
|
|
||||||
|
|
||||||
## Contact Alternatives
|
|
||||||
|
|
||||||
If you are unable to send an email, please open an issue on GitHub without disclosing details such that we can establish a alternative form of communication.
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ var nameFormat = '${name.tenantId}-${name.projectId}-${environment}-${name.regio
|
||||||
Resource Group
|
Resource Group
|
||||||
*/
|
*/
|
||||||
|
|
||||||
resource ResourceGroup 'Microsoft.Resources/resourceGroups@2024-03-01' = {
|
resource ResourceGroup 'Microsoft.Resources/resourceGroups@2023-07-01' = {
|
||||||
name: format(nameFormat, 'RG', 1)
|
name: format(nameFormat, 'RG', 1)
|
||||||
location: location
|
location: location
|
||||||
tags: tags
|
tags: tags
|
||||||
|
|
|
@ -16,7 +16,7 @@ var accessPolicies = [for identity in identities: {
|
||||||
Log Analytics Workspace (existing)
|
Log Analytics Workspace (existing)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
resource _logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2023-09-01' existing = {
|
resource _logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' existing = {
|
||||||
name: format(nameFormat, 'LAW', 1)
|
name: format(nameFormat, 'LAW', 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ param tags object
|
||||||
Log Analytics Workspace
|
Log Analytics Workspace
|
||||||
*/
|
*/
|
||||||
|
|
||||||
resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2023-09-01' = {
|
resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' = {
|
||||||
name: format(nameFormat, 'LAW', 1)
|
name: format(nameFormat, 'LAW', 1)
|
||||||
location: location
|
location: location
|
||||||
tags: tags
|
tags: tags
|
||||||
|
|
92
src/main.rs
92
src/main.rs
|
@ -1,31 +1,17 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use azure_identity::{DefaultAzureCredential, TokenCredentialOptions};
|
use azure_core::error::HttpError;
|
||||||
|
use azure_identity::DefaultAzureCredential;
|
||||||
use azure_security_keyvault::prelude::KeyVaultGetSecretsResponse;
|
use azure_security_keyvault::prelude::KeyVaultGetSecretsResponse;
|
||||||
use azure_security_keyvault::KeyvaultClient;
|
use azure_security_keyvault::KeyvaultClient;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use futures::stream::StreamExt;
|
use futures::stream::StreamExt;
|
||||||
use paris::{error, Logger};
|
use paris::{error, Logger};
|
||||||
use std::error::Error;
|
|
||||||
use std::fmt;
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
use tokio::sync::Semaphore;
|
use tokio::sync::Semaphore;
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct CustomError {
|
|
||||||
message: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for CustomError {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(f, "{}", self.message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Error for CustomError {}
|
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[clap(author, version, about, long_about = None)]
|
#[clap(author, version, about, long_about = None)]
|
||||||
struct Opts {
|
struct Opts {
|
||||||
|
@ -49,15 +35,12 @@ async fn check_vault_dns(vault_name: &str) -> Result<()> {
|
||||||
|
|
||||||
match lookup_result {
|
match lookup_result {
|
||||||
Ok(_) => Ok(()),
|
Ok(_) => Ok(()),
|
||||||
Err(_err) => {
|
Err(err) => {
|
||||||
error!("DNS lookup failed for Key Vault: {}", vault_name);
|
error!("DNS lookup failed for Key Vault: {}", vault_name);
|
||||||
error!(
|
error!(
|
||||||
"Please check that the Key Vault exists or that you have no connectivity issues."
|
"Please check that the Key Vault exists or that you have no connectivity issues."
|
||||||
);
|
);
|
||||||
Err(CustomError {
|
Err(err.into())
|
||||||
message: "An error occurred while fetching secrets".to_string(),
|
|
||||||
}
|
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,33 +56,27 @@ async fn fetch_secrets_from_key_vault(
|
||||||
let page = match page {
|
let page = match page {
|
||||||
Ok(p) => p,
|
Ok(p) => p,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
Logger::new().newline(1);
|
error!("\n");
|
||||||
match err.as_http_error() {
|
error!("Failed to fetch secrets.");
|
||||||
Some(err) => {
|
let specific_error = err.downcast_ref::<HttpError>();
|
||||||
if err
|
if let Some(specific_error) = specific_error {
|
||||||
.error_message()
|
if specific_error
|
||||||
.unwrap()
|
.error_message()
|
||||||
.contains("does not have secrets list permission on key vault")
|
.unwrap()
|
||||||
{
|
.to_string()
|
||||||
error!("Make sure you have List permissions on the Key Vault.")
|
.contains("does not have secrets list permission on key vault")
|
||||||
} else if err
|
{
|
||||||
.error_message()
|
error!("Make sure you have List permissions on the Key Vault.");
|
||||||
.unwrap()
|
} else if specific_error
|
||||||
.contains("is not authorized and caller is not a trusted service")
|
.error_message()
|
||||||
{
|
.unwrap()
|
||||||
error!("Make sure you're on the Key Vaults Firewall allowlist.")
|
.to_string()
|
||||||
} else {
|
.contains("is not authorized and caller is not a trusted service")
|
||||||
error!("HTTP Error: {}", err);
|
{
|
||||||
}
|
error!("Make sure you're on the Key Vaults Firewall allowlist.");
|
||||||
}
|
}
|
||||||
_ => {
|
|
||||||
error!("Error: {}", err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return Err(CustomError {
|
|
||||||
message: "An error occurred while fetching secrets".to_string(),
|
|
||||||
}
|
}
|
||||||
.into());
|
return Err(err.into());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
secret_values
|
secret_values
|
||||||
|
@ -177,21 +154,15 @@ fn create_env_file(secrets: Vec<(String, String)>, output_file: &str) -> Result<
|
||||||
Ok(f) => f,
|
Ok(f) => f,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("Failed to create output file: {}", err);
|
error!("Failed to create output file: {}", err);
|
||||||
return Err(CustomError {
|
return Err(err.into());
|
||||||
message: "n Aerror occurred creating file".to_string(),
|
|
||||||
}
|
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for (key, value) in secrets {
|
for (key, value) in secrets {
|
||||||
if let Some(secret_name) = key.split('/').last() {
|
if let Some(secret_name) = key.split('/').last() {
|
||||||
if let Err(_err) = writeln!(file, "{}={}", secret_name, value) {
|
if let Err(err) = writeln!(file, "{}={}", secret_name, value) {
|
||||||
error!("Failed to write to output file: {}", output_file);
|
error!("Failed to write to output file: {}: {}", output_file, err);
|
||||||
return Err(CustomError {
|
return Err(err.into());
|
||||||
message: "An error occurred while writing secrets to file".to_string(),
|
|
||||||
}
|
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -232,17 +203,12 @@ mod tests {
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
let opts: Opts = Opts::parse();
|
let opts: Opts = Opts::parse();
|
||||||
let mut log: Logger<'_> = Logger::new();
|
let mut log = Logger::new();
|
||||||
|
|
||||||
let vault_url = format!("https://{}.vault.azure.net", opts.vault_name);
|
let vault_url = format!("https://{}.vault.azure.net", opts.vault_name);
|
||||||
|
|
||||||
log.loading("Detecting credentials.");
|
log.loading("Detecting credentials.");
|
||||||
let credential_options = TokenCredentialOptions::default();
|
let credential = DefaultAzureCredential::default();
|
||||||
let credential =
|
|
||||||
DefaultAzureCredential::create(credential_options).map_err(|e| CustomError {
|
|
||||||
message: format!("Failed to create DefaultAzureCredential: {}", e),
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let client = match KeyvaultClient::new(&vault_url, std::sync::Arc::new(credential)) {
|
let client = match KeyvaultClient::new(&vault_url, std::sync::Arc::new(credential)) {
|
||||||
Ok(c) => c,
|
Ok(c) => c,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
|
Loading…
Reference in a new issue